python-面向对象
# --思考,理解--
# 世界万物皆可分类。
# 世界万物皆为对象。
# 只要是对象,必属于某一个分类。
# 只要是对象,必有自己的属性。
# 三大特性。
# 封装 一个类中的属性或者方法,对于外部调用时是透明的。
# 继承 一个类可以派生出子类,父类中的属性方法自动被子类继承。
# 多态 一个接口,多种实现。例如:厂长发出工作指令,客服部开始打电话工作,装箱工人开始装箱工作,装车工人开始装车工作...一个工作指令,不同部门开始不同的工作。
# 代码实现理解。
# 这里定义了一个人类的模板。 class person: def __init__(self,name,sex): self.name = name self.sex = sex def introduce(self): print('你好,我叫',self.name,'性别是',self.sex) def sleep(self): print(self.name,'睡觉了...') def eat(self): print(self.name,'吃饭了....') def buy(self): print(self.name,'买了东西...') # 上帝按照人类模板创造了三个人类 p1 = person('赵一','男') p2 = person('钱二','男') p3 = person('孙三','男') # 创造出的人类同时自我介绍之后,分别干了不同的事。 p1.introduce() p1.eat() p2.introduce() p2.buy() p3.introduce() p3.sleep() # 由此可见,面向对象的优点:1.类的功能属性一目了然。2.代码复用性高。
# 【详细理解】
# 我们再看看类,对象在内存中是怎么工作的?
# class 在python中是定义一个类的关键字,后面紧跟的是类的名字。所以 class person: 定义了一个名为person的class。
# 重点:类未实例化时,是已经存在内存中的。但是不能做任何操作。
class person: boby = '身体' #类变量,不实例化就能调用。 def __init__(self,name): print('self',self) self.name = name #实例变量,实例化之后才能调用 def introduce(self): print('introduce_self',self) print('你好,我是',self.name) # 未实例的class,已经存在于内存中 print(person) # <class '__main__.person'> # 实例后的class,称为对象。 # 由例子可知:实例化时,把自己实例化的内存地址传入了对象内,对象中调用其实是实例化时的内存地址引用。 print(person.boby) person.boby = '张三的身体' print(person.boby) p1 = person('李三') print(p1) p1.introduce() # 身体 # 张三的身体 # self <__main__.person object at 0x0000000000B73B00> # <__main__.person object at 0x0000000000B73B00> # introduce_self <__main__.person object at 0x0000000000B73B00> print(person.boby) p2 = person('张四') print(p2) p2.introduce() # 张三的身体 # self <__main__.person object at 0x0000000000B73BE0> # <__main__.person object at 0x0000000000B73BE0> # introduce_self <__main__.person object at 0x0000000000B73BE0> # 你好,我是 张四 # 现在张四觉得自己的名字不好听,想改名字。还想多加一个年龄的东西。 p2.name = '张五' p2.age = 18 p2.introduce() print(p2.age) # introduce_self <__main__.person object at 0x0000000000B73BE0> # 你好,我是 张五 # 18 # boby = '身体' 是类的变量,整一个类共享。 # self 即是类实例化的内存空间地址。 # self.name = 类实例化的变量,作用是其类的本身。 # def __init__(self): init是类中python对象中自带的一个特殊的方法,叫做构造方法,实例化类时,第一个执行的就是init方法,也称做类的初始化工作。 # def introduce(self): 是自己自定义的一个普通方法。
# 私有方法,私有属性
class person: def __init__(self,name,deposit): self.name = name self.__deposit = deposit # 私有属性,两个下划线定义私有属性,只能由内部使用。 def introduce(self): print('你好,我是',self.name) def buy(self,goodprice): print(self.name,'的存款为',self.__deposit) self.__layout(goodprice) print(self.name,'购买价格为{price}的商品,现在存款为{deposit}'.format(price=goodprice,deposit=self.__deposit)) # 私有方法,存款的使用只能内部使用。 def __layout(self,goodprice): self.__deposit -= goodprice # 析构方法,对象销毁时会自动调用次方法,与init是一对。与人的出生和死亡对应。 def __del__(self): print(self.name,'安享天年了...') #print(p1.__deposit) #AttributeError: 'person' object has no attribute '__deposit' #p1.__layout(2000) #AttributeError: 'person' object has no attribute '__layout' p1 = person('张三',20000) p1.introduce() p1.buy(988) # 你好,我是 张三 # 张三 的存款为 20000 # 张三 购买价格为988的商品,现在存款为19012 # 张三 安享天年了...
# 继承
# 两种类,继承中的两种写法。 # 经典类,py2 class person: pass # 新式类,py3 class good(object): pass
# 继承的特点和要点。
class person: def __init__(self,name,age): print('person的self内存地址',self) self.name = name self.age = age def sleep(self): print(self.name,'睡觉了...') def eat(self): print(self.name,'吃饭了...') def talk(self): print(self.name,'说话了...') def __creator(self): print('上帝') def __del__(self): print(self.name,'安享天年了...')
# 括号中说明:man类继承person类的所有的属性和方法。 class man(person): # 继承父类的构造方法,然后自定义自己的构造方法。 def __init__(self,name,age,life): super(man,self).__init__(name,age) # 先调用父类方法。推荐。 # person.__init__(self, name, age) #先调用父类的另一种方式。功能同上。 self.life = life def daiba(self): print('man的self内存地址',self) # 继承中,子类对象使用的内存地址是父类的对象的内存地址。 print(self.name,'带把的生命是',self.life) def talk(self): print(self.name,'man重写了person','说话了') m1 = man('张三',23,80) m1.daiba() m1.sleep() # 继承了person的睡觉。 m1.talk() #m1.__creator() 但是不能继承父类中的私有属性和私有方法 #AttributeError: 'man' object has no attribute '__wife' # person的self内存地址 <__main__.man object at 0x0000000000709A20> # man的self内存地址 <__main__.man object at 0x0000000000709A20> # 张三 带把的生命是 80 # 张三 睡觉了... # 张三 man重写了person 说话了 # 张三 安享天年了...
# 多继承的顺序
class person(object): def __init__(self,name): self.name = name def eat(self): print(self.name,'吃饭了..') class Man(person): def man(self): print(self.name,'男性...') def sleep(self): print('man睡觉') class Woman(person): def birth(self): print(self.name,'生孩子了...') def sleep(self): print('woman睡觉') def eat(self): print('woman吃饭了。。。') # 多继承方式如下 class Children(Man,Woman): def talk(self): print('我是孩纸...') # 问题1:继承多个父类,父类中有相同的方法和属性,继承顺序如何判定? # 答:继承顺序从左到右。如:Children(Man,Woman): 先Man后Woman 例子:c1.sleep() # 问题2:继承多个父类,而且其中一个父类还继承了其他父类,继承顺序是如何判定? # 答:继承顺序还是从左往右,再往上寻找。
# 经典类时按深度优先进行查找,新式类时按广度优先进行查找。py2默认是按深度,py3默认是按广度。
c1 = Children('张小小') c1.man() c1.sleep() c1.eat() # 张小小 男性... # man睡觉 # woman吃饭了。。。
# 多继承的self问题?
# 思考,以下代码调用的事哪一个eat()? # 答,Man的eat().因为man 已经继承了person的get_eat()。 # 经典类时按深度优先进行查找,新式类时按广度优先进行查找。py2默认是按深度,py3默认是按广度。 # 而且由此可见,self 永远是指向当前实例化的对象,和继承没有半毛钱关系。 class person(object): def get_eat(self): self.eat() def eat(self): print('person:',self) class Man(person): def eat(self): print('Man:',self) class Son(Man,person): pass s1 = Son() print('s1:',s1) s1.get_eat() # s1: <__main__.Son object at 0x0000000001049908> # Man: <__main__.Son object at 0x0000000001049908>
# 构造方法,析构方法,静态方法,类方法,普通方法。
class food(object): name = '类变量' def __init__(self,name,color): """ 构造方法,实例化类时便开始执行。 :param name: :param color: """ print('这是构造方法....') self.name = name def grow(self): print('这是一个普通方法....') @classmethod def set(cls): """ 只能访问类变量。 :return: """ print('这是一个类方法....',cls.name) cls.get() @staticmethod def get(): """ 实际上和类没有了关系,只是放在这个类中。 由不添加self可以看出 :return: """ print('这是一个静态方法....') @property def lists(self): """把一个方法变成属""" print('这是一个属性方法....') def __del__(self): """ 对象销毁时,自动执行该方法。 :return: """ print('这是一个析构方法...') food.get() f1 = food('苹果','red') f1.set() f1.lists f1.grow() # 这是一个静态方法.... # 这是构造方法.... # 这是一个类方法.... 类变量 # 这是一个静态方法.... # 这是一个普通方法.... # 这是一个析构方法...
额外的理解:
# 类的特殊成员方法
# __doc__ __module__ __class__ __call__ __dict__ __str__
class food(object): """这是一个关于食物的类""" pass def __call__(self, *args, **kwargs): print('这是个call方法') def __str__(self): # 设置类的别名 return 'food类' print(food.__doc__) # 说明类的描述信息。 print(food.__module__) # 说明从哪个模块而来 print(food.__class__) # 说明从哪个类而来 f1 = food() f1() # __call__ 类实例化之后,还能实例化调用。 print(food.__dict__) # 查看类或者对象的所有的成员。 print(f1.__dict__) # 查看实例化后的对象的的成员属性。 print(f1) # 查看类的别名。
# 类的 __getitem__ __setitem__ __delitem__
class food(object): def __init__(self): self.data = {} def __getitem__(self, item): print('getitem',item) return self.data.get(item) def __setitem__(self, key, value): print('setitem',key,value) self.data[key]=value def __delitem__(self, key): print('delitem',key) # 设置类的变量可以更加简单的编辑。 # 看如下的例子 f1 = food() f1['name'] = 'Dog' name = f1['name'] print(name) del f1['name'] # setitem name Dog # getitem name # Dog # delitem name
# 类实例化之前的定制。
class food(object): def __init__(self): self.name = 'ddddddd' print('init......') def __new__(cls, *args, **kwargs): """ 重写实例化开始的操作. :param args: :param kwargs: :return: """ print('实例化.....') return object.__new__(cls) # 继承object的new方法,继承父类的实例化方法。 f1 =food() print(f1.name) # 实例化..... # init...... # ddddddd
练习代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# 成员属性,分页小程序。 class pages: def __init__(self,current_page): try: p = int(current_page) except Exception as e: p = 1 self.curpage = p self.totalcount = totalcount @property def startpage(self): val = (self.curpage-1) * 10 return val @property def endpage(self): val = self.curpage * 10 return val li = [] for i in range(100): li.append(i) while True: inp = input('请输入你想查看的页面数:') obj = pages(inp) print(li[obj.startpage:obj.endpage])