概念
类、对象
""" 面向对象 """ class Person(object): def __init__(self, name, age): # 初始化 self.name = name self.age = age def eat(self, food): pass p = Person('sunchangheng', 26) # 实例化 print(p.age) print(p.__dict__) # 查看对象的所有属性和值 print(Person.__dict__) # 查看类的所有方法
类
相当于模板
查看类中的方法:类名.__dict__
对象
相当于同通过模板创造出来的实实在在的东西
1、查看所有属性和值:对象名.__dict__
2、单独查看某个属性:对象名.某个属性
实例化、实例
实例化
从类中创造一个类出来的过程
对象被实例化的时候,创建了一个类对象指针,类对象指针指向类命名空间
实例
从类里创建出来的对象即成为实例
self
-
对象就是一个self,self指向实例好的对象
-
self是一个可以存储很多属性的大字典
-
self拥有的属性都是属于对象的
属性
创建一个类就会创建一个类的名称空间,用来存储类中定义的所有名字,这些名字称为类的属性
而类有两种属性:静态属性和动态属性
- 静态属性:直接在类中定义的变量
- 动态属性:实例化对象时创建的属性
特性
继承
一个类可以被多个类继承
一个类可以继承多个父类 -->python里
"""主动调用父类的方法""" class BasePerson(object): def __init__(self, age, gender): self.age = age self.gender = gender def walk(self): print('base walk') def talk(self): print('base talk') class SuperMan(BasePerson): def __init__(self, age, gender): # 继承父类的属性 super(SuperMan, self).__init__(age, gender) # 方式一 # BasePerson.__init__(self, age, gender) # 方式二 def walk(self): # BasePerson.walk(self) # 方式一 super(SuperMan, self).walk() # 方式二 print('superman walk') def talk(self): # BasePerson.talk(self) print('superman talk') super_man = SuperMan('18', '1') super_man.walk() print(super_man.age)
单继承
派生属性:父类中没有的属性,在子类中出现
派生方法:父类中没有的方法,在子类中出现
只要子类的对象调用子类中有的名字(方法),一定先用子类的,子类中没有才找父类的,如果父类也没有就报错
如果子类和父类都有的名字(方法),先用 子类的,如果还想调用父类的,需要自己传self参数
调用父类的方法
父类名.方法(对象)
super(子类,对象).方法名() # super方法只在python3中存在
继承父类的属性
在子类的init方法下
其实就是利用上面的主动调用父类的__init__方法实现的继承父类属性
注意:super的本质不是单纯找父类,而是根据调用者的节点位置的广度优先顺序来的
多继承
接口隔离原则:使用多个专门的接口,而不使用单一的总接口。即客户端不应该依赖那些不需要的接口。
Python 2.x中默认都是经典类,只有显式继承了object才是新式类
Python 3.x中默认都是新式类,不必显式的继承object
旧式类和新式类默认按照: 深度搜索
当遇到广度和深度两个选择时(例如钻石继承)
新式类 广度优先搜索,且有 __mro__方法(记录新式类中的继承顺序)
旧式类 深度优先搜索。
多态
-
不依赖父类的情况下实现两个相识的同名方法
-
鸭子类型:如果两个类刚好相似,并不产生父类-子类的关系,而是鸭子类型
-
list、tuple这种类似同名方法,是通过写代码的时候约束的,而不是通过父类约束
-
优点:松耦合,每个相似的类之间都没有影响
-
缺点:太随意,只能靠自觉去怎么定义一个类似的方法
封装
代码的保护,面向对象的思想本身就是一种
只让对象自己内部能调用类中的方法、属性
属性和方法都藏起来,不让你看见
父类中的所有私有属性不能被子类调用
调用
- 内部使用:对象名.__私有属性名
""" 私有属性 """ class SunChangHeng(object): country = 'china' def __init__(self, age, name): self.__age = age # 私有属性,只可以在对象内部使用 self.name = name def get_age(self): print('你的私有年龄是: ' % self.__age) sun = SunChangHeng(19, 'sun') print(sun.name) # print(sun.__age) # 访问不到
私有
对象的属性
类中的方法
类中的静态属性
组合
一个对象的属性值是另一类的对象
""" 组合使用 """ class Birth(object): def __init__(self, year, month, day): self.year = year self.month = month self.day = day class Person(object): def __init__(self, name, birthday): self.name = name self.birthday = birthday bir = Birth(1993, 8, 21) sun = Person('sunchangheng', bir) print(sun.birthday.__dict__)
方法
类方法
@classmethod装饰
把一个方法变成一个类方法,这个方法就直接可以被类调用,不需要依托对象
需要传cls参数
当这个方法只涉及静态属性的时候,就应该使用classmethod来装饰这个方法
""" 类方法 """ class Goods(object): __discount = 0.8 def __init__(self, name, price): self.name = name self.__price = price @property def price(self): return self.__price * Goods.__discount @classmethod def set_discount(cls, discount): cls.__discount = discount iphone4 = Goods('apple iphone4', 4999) print(iphone4.price) Goods.set_discount(0.9) print(iphone4.price)
类静态方法
@staticmethod装饰
将类中的一个方法变成一个普通函数(静态方法),但还是要通过类名.方法()调用
如果一个函数既和对象没有关系,也和类没有关系,那么就用staticmethod装饰这个函数
""" 将类中的一个方法变成一个普通函数(静态方法),但还是要通过类名.方法()调用 """ class BaseMath(object): """ 工具包 """ @staticmethod def add(a, b): return a + b @staticmethod def reduce(a, b): return a - b @staticmethod def multiply(a, b): return a * b @staticmethod def div(a, b): return a / b print(BaseMath.add(10, 8)) print(BaseMath.reduce(10, 8)) print(BaseMath.multiply(10, 8)) print(BaseMath.div(10, 8))
类计算属性
@property装饰
将类中的一个方法伪装成一个属性
配合setter、deleter使用
""" 将类中的一个方法伪装成一个属性 计算属性 """ from math import pi class Circle(object): def __init__(self, r): self.r = r @property def perimeter(self): return 2 * pi * self.r @property def area(self): return 2 * pi * self.r ** 2 c1 = Circle(8) print(c1.perimeter) print(c1.area)