面向对象的三要素
封装
class Turtle: # python 中的类age = 'green'weight = 10legs = 4shell = Truemouth = '大嘴'# 方法def climb(self):print('我在很努力')def run(self):print('运行')def bite(self):print('陶死你')def add(self):print('加法运算')t = Turtle()t.climb()
继承
继承是子类自动共享父类之间数据和方法的机制
'''Mylist 继承 list 列表的方法pass 表示占位Mylist 这个类不做任何事情, 达到信息隐蔽'''class Mylist(list):pass# 实例化 Mylist 实例对象list2 = Mylist()list2.append(5)list2.append(9)list2.append(15)print(list2)# 也可以进行排序print(list2.stor())------------------------------->>>>[5, 19, 15]>>>>[5, 15, 19]
多态
'''多态就是 不同对象 对同一方法 响应不同的行动'''class A:def fun(self):print('我是A对象里的函数')class B:def fun(self):print('我是B对象里的函数')a = A()b = B()a.fun()b.fun()------------------>>>我叫张三, 该死的, 谁踢我....>>>我叫李四, 该死的, 谁踢我....>>>我叫小明, 该死的, 谁踢我....
self 是什么?
python的 self 就相当于 JavaScript 中的 this 的指针
# self 指针 相当于 JavaScript中的 this 指针# 这个类相当于模版一样,class Ball:def setName(self, name):self.name = namedef cick(self):print("我叫%s, 该死的, 谁踢我...." %self.name)a = Ball()a.setName("张三")b = Ball()b.setName("李四")c = Ball()c.setName("小明")a.cick()b.cick()c.cick()-------------------->>>我叫张三, 该死的, 谁踢我....>>>我叫李四, 该死的, 谁踢我....>>>我叫小明, 该死的, 谁踢我....
访问控制与属性装饰器
在python 中定义私有变量 只需要在变量或者函数名前加上 “__” 两个下划线, 那么这个函数或变量就会为私有 外部访问不了 , 同时也称为装饰器
共有变量函数
# 共有 ,可以被外部访问的class temp:age = 18def setName(self, name):print('我叫:%s' % name)A = temp()print(A.age)A.setName('张三')------------------->>>18>>>我叫:张三
访问私有变量函数1
'''定义私有函数或者变量 在变量或者函数前 添加 __ 双下划线即可然后调用共有的方法, 获取内部私有的变量或者函数'''class temp:__age = 18def __setName(self, name):print('我叫:%s' % name)def getAge(self):print('age的值:%s' % self.__age)def getName(self,name):self.__setName(name)A = temp()A.getAge()A.getName('李四')--------------------------------->>>18>>>我叫:李四
访问私有变量函数2
class temp:__age = 18def __setName(self, name):# print('我叫:%s' % name)return '我叫:%s' % namedef getAge(self):print('age的值:%s' % self.__age)def getName(self,name):self.__setName(name)A = temp()A.getAge()A.getName('李四')# 还可以通过 下划线类名 进行访问也可以print(A._temp__age)print(A._temp__setName('王五'))--------------------------------->>>age的值:18>>>18>>>我叫:王五
类和实例
# 类class Turbo:name = '张三'def add(a,b):return a + b# 实例化 出了 tt = Turbo()t.name
类方法与静态方法
静态方法 @staticmethod
为什么会报错?
静态方法不能访问实例属性、类属性、实例方法、类方法
class Test2:name ="你好世界"@staticmethoddef static(self):print("我的口号是:" +self.name)temp2 = Test2()temp2.static()# static 已经通过 @staticmethod 定义成静态方法, 所以不能直接这样访问,因为 self是上下文访问 属性name, 当然也包括这个 self---------------------报错TypeError: static() missing 1 required positional argument: 'self'
静态方法的特别之处
- 它跟类与对象无关
 - 跟在模块中直接定义普通函数没有什么区别,只是把“静态方法”放到了类里面,所以只能设置形参
 - 只能通过 类名.静态方法 来调用 ```python
 
class Test: name =”你好世界”
@staticmethoddef static(name):print("我的口号是:" +name)
temp = Test()
temp.static(temp.name)
Test.static(temp.name)
我的口号是:你好世界 我的口号是:你好世界
<a name="Bqd4L"></a>### 类方法 @classmethod```pythonclass person:name = "cool man"@classmethoddef class_m(cls):print("--第一个类方法--", id(cls))print("--第一个类方法--", cls.name)cls.self_m(cls)cls.class_m2()def self_m(self):print("--实例方法--", id(self))print("--实例方法--", self.name)@classmethoddef class_m2(cls):print("--第二个类方法--", id(cls))p = person()p.name = "bad boy" # 绑定实例属性p.class_m()person.class_m()
知识点
- 类方法内部可以直接访问类属性、类方法、实例方法
 - 可以理解成类对象的引用,哪一个类对象调用的方法, cls 就是哪个一个类的引用, 类对象.类方法 ;和实例方法中的 self 很像, 实例对象.实例方法
 
cls
- 调用其他类方法时,不用传递cls参数;但调用其他实例方法时,需要传递cls参数
 - 在类方法内部调用的实例方法,接收的是一个类对象而不是实例对象,当实例对象绑定实例属性时,在实例方法中打印的仍然是类属性;表明类方法无法访问实例属性
 一个类只有一个类对象,即使通过实例对象调用类方法,传递的仍然是类对象的引用,所有类方法都被同一个类对象调用
思考题
如果方法内部 即需要访问 实例属性,又需要访问 类属性,应该定义成什么方法?
答案:实例方法,因为可以通过 类对象.类属性 来访问,但在类方法中无法访问实例属性 ```python class Person: name = “bad boy”def self_m(self):
Person.name = "yep"print(self.name)
p = Person() p.name = “陈十八” # 绑定实例属性 p.self_m()
Person.self_m(Person)
陈十八 yep
<a name="h3sYt"></a>## 继承与多态<a name="usqCm"></a>### 子继承父类```pythonclass Panent:def hello(self):print('正在调用父类的方法....')class Child(Panent):passp = Panent()p.hello()c=Child()c.hello()----------->>>正在调用父类的方法....>>>正在调用父类的方法....
如果子类中定义与父类同名的方法或者属性, 则会自动覆盖父类对应的方法或属性
class Panent: # 这个是父类def hello(self):print('正在调用父类的方法....')class Child(Panent): # 这个是子类def hello(self):print('正在调用子类的方法....')p = Panent()p.hello()c=Child()c.hello()----------->>>正在调用父类的方法....>>>正在调用子类的方法....
小案列
鲨鱼移动 的代码 会报错 为什么呢, 可是代码都相同啊!
因为 我们重写 init方法, 子类重写了父类的方法, 就会覆盖原来的方法
import random as rclass Fish: # 鱼def __init__(self):self.x = r.randint(0, 10)self.y = r.randint(0, 10)def move(self):self.x -= 1print("我的位置是:", self.x, self.y)class Goldfish(Fish): # 金鱼passclass Carp(Fish): # 鲤鱼passclass Salmon(Fish): # 三文鱼passclass Shark(Fish):def __init__(self):self.hungry = Truedef eat(self):if self.hungry:print("吃货的梦想就是天天有的吃")self.hungry = Falseelse:print("太撑了, 吃不下")fish = Fish()fish.move()goldfish = Goldfish() # 金鱼移动goldfish.move()shark = Shark() # 鲨鱼移动shark.move()---------------------我的位置是: 5 8我的位置是: 5 5Traceback (most recent call last):File "e:/001笔记大全/008Python01/demon10.py", line 40, in <module>shark.move()File "e:/001笔记大全/008Python01/demon10.py", line 8, in moveself.x -=1AttributeError: 'Shark' object has no attribute 'x'
我们要在重写init 方法的时候
解决方法1
调用未绑定的父类方法
应该要在鲨鱼的类里面        重写init 方法的时候先调用子类的init方法
只需要书写父类的名字 Fish.init(self)
import random as rclass Fish: # 鱼def __init__(self):self.x = r.randint(0, 10)self.y = r.randint(0, 10)def move(self):self.x -= 1print("我的位置是:", self.x, self.y)class Goldfish(Fish): # 金鱼passclass Carp(Fish): # 鲤鱼passclass Salmon(Fish): # 三文鱼passclass Shark(Fish):def __init__(self):'''原理, 子类中有跟父类一样的方法会覆盖父类的方法, 所以在修改前 添加这段代码即可注意: Fish.__init__(self)是调用父类的而self 是子类的实列对象'''Fish.__init__(self)self.hungry = Truedef eat(self):if self.hungry:print("吃货的梦想就是天天有的吃")self.hungry = Falseelse:print("太撑了, 吃不下")fish = Fish()fish.move()goldfish = Goldfish() # 金鱼移动goldfish.move()shark = Shark() # 鲨鱼移动shark.move()---------------------我的位置是: 9 0我的位置是: 9 9我的位置是: 8 8
解决办法2
使用 super 函数 能够帮我们自动找到基类的方法, 还能帮我们传参数
import random as rclass Fish: # 鱼def __init__(self):self.x = r.randint(0, 10)self.y = r.randint(0, 10)def move(self):self.x -= 1print("我的位置是:", self.x, self.y)class Goldfish(Fish): # 金鱼passclass Carp(Fish): # 鲤鱼passclass Salmon(Fish): # 三文鱼passclass Shark(Fish):def __init__(self):# Fish.__init__(self)super().__init__()self.hungry = Truedef eat(self):if self.hungry:print("吃货的梦想就是天天有的吃")self.hungry = Falseelse:print("太撑了, 吃不下")fish = Fish()fish.move()goldfish = Goldfish() # 金鱼移动goldfish.move()shark = Shark() # 鲨鱼移动shark.move()--------------------------------我的位置是: 2 0我的位置是: 1 9我的位置是: 2 3
多重继承
可以继承多重父类的方法
注意, 请尽量避免使用它
class Base1:def fun1(self):print("我是fun1d.")class Base2:def fun2(self):print("我是fun2.")class C(Base1, Base2):passb = C()b.fun1()b.fun2()---------------------我是fun1d.我是fun2.
继承与多继承(组合)
思路提示 : 
定义一个水池类
水池里有乌龟类, 金鱼类等等
如果使用继承和多继承显然不行, 乱搞
那怎么样才能组成一个和谐的类呢? 使用组合即可
所谓的组合就是把旧类放到新类里, 这样就组合进去了
# 水池组合class Turtle: # 乌龟def __init__(self, x): # x 表示有多少个乌龟进来self.num = xclass Fish: # 金鱼def __init__(self, x): # xself.num = xclass Pool: # 水池def __init__(self, x, y):self.turtle = Turtle(x)self.fish = Fish(y)def print_num(self):print("水池里总共有乌龟 %d 只, 小鱼 %d 条" % (self.turtle.num, self.fish.num))# 组合就是 把2 个旧类 实列化 放到 新的类里面 那么就把旧类 组合进去了,pool = Pool(2,10)pool.print_num()--------------------------水池里总共有乌龟 1 只, 小鱼 10 条
