1. 类的组成

    1. class Student:
    2. native_place = '吉林' #类属性
    3. __type = 'Person' #类的私有属性
    4. def __init__(self,name,age): #name ,age为实例属性
    5. self.name = name
    6. self.age = age
    7. #实例方法
    8. def info(self):
    9. print("my name is %s,my age is %s" % (self.name,self.age))
    10. #类方法 当方法中需要使用类对象 (如访问私有类属性等)时,定义类方法可以获取
    11. @classmethod
    12. def get_type(cls):
    13. print('类方法')
    14. return cls.__type
    15. #静态方法 静态方法不会自动传递实例对象和类对象
    16. @staticmethod
    17. def sm():
    18. print('静态方法')
  2. 类的对象

    1. stu = Student('Jack',30) #创建一个实例对象
    2. stu.info() #调用实例方法
    3. print(stu.name) #实例属性
    4. print(stu.age) #实例属性
    5. print(stu.native_place) #类属性
    6. #动态改变类属性
    7. Student.native_place = '天津'
    8. print(stu.native_place) #输出为天津
  3. 类方法和静态方法

当方法中 既不需要使用实例对象(如实例对象,实例属性),也不需要使用类对象 (如类属性、类方法、创建实例等)时,定义静态方法
取消不需要的参数传递,有利于 减少不必要的内存占用和性能消耗

  1. Student.get_type()
  2. >>Person
  3. Student.sm()
  4. >>静态方法

三大特性

  1. 封装

将数据的属性和行为包装到类对象中,python中如果要使用私有属性或者类,在前面使用’__’

  1. class Student:
  2. def __init__(self,name,age):
  3. self.name = name
  4. self.__age = age
  5. def show(self):
  6. print('这个学生的名字是%s ,年龄是%d' %(self.name,self.__age))
  7. stu1 = Student('张三',20)
  8. print(stu1.show())
  9. print(stu1.name)

print(stu1.__age)
print(stu1._Student__age) 可以这样输出 私有属性

  1. 继承
    1. Class Person:
    2. def __init__(self,name,age):
    3. self.name = name
    4. self.age = age
    5. def info(self):
    6. print('姓名:{0} 年龄:{1}'.format(self.name,self.age))
    7. Class Student(Person):
    8. def __init__(self,name,age,score):
    9. super().__init__(name,age)
    10. self.score=score
    11. def info(self):
    12. super().info()
    13. print('成绩:{0}'.format(self.score))
    14. Class Teacher(Person):
    15. def __init__(self,name,age,year):
    16. super().__init__(name,age) #继承父类的方法和属性
    17. self.year = year
    18. stu1 = Student('李四',30,100)
    19. stu1.info() #方法重写了,调用子类的方法
    20. teacher = Teacher('张梅',40,'初三')
    21. teacher.info() #直接使用父类的方法

    super()的方法

  1. class Base(object):
  2. def __init__(self):
  3. print("enter Base")
  4. print("leave Base")
  5. class A(Base):
  6. def __init__(self):
  7. print("enter A")
  8. super(A,self).__init__()
  9. print("leave A")
  10. class B(Base):
  11. def __init__(self):
  12. print("enter B")
  13. super(B,self).__init__()
  14. print("leave B")
  15. class C(A,B):
  16. def __init__(self):
  17. print("enter C")
  18. super(C,self).__init__()
  19. print("leave C")
  20. c = C()
  21. >>>>
  22. enter C
  23. enter A
  24. enter B
  25. enter Base
  26. leave Base
  27. leave B
  28. leave A
  29. leave C

MRO列表:
事实上,对于你定义的每一个类,Python 会计算出一个方法解析顺序(Method Resolution Order, MRO)列表,它代表了类继承的顺序,我们可以使用下面的方式获得某个类的 MRO 列表。这个列表真实的列出了类C的继承顺序。C->A->B->Base->object。在方法调用时,是按照这个顺序查找的。
那这个 MRO 列表的顺序是怎么定的呢,它是通过一个 C3 线性化算法来实现的,这里我们就不去深究这个算法了,感兴趣的读者可以自己去了解一下,总的来说,一个类的 MRO 列表就是合并所有父类的 MRO 列表,并遵循以下三条原则:

  • 子类永远在父类前面
  • 如果有多个父类,会根据它们在列表中的顺序被检查
  • 如果对下一个类存在两个合法的选择,选择第一个父类

    1. def super(cls, inst):
    2. mro = inst.__class__.mro()
    3. return mro[mro.index(cls) + 1]

    其中,cls 代表类,inst 代表实例,上面的代码做了两件事

  • 获取 inst 的 MRO 列表

  • 查找 cls 在当前 MRO 列表中的 index, 并返回它的下一个类,即 mro[index + 1]

这里的 self 是当前 C 的实例,self.class.mro() 结果是

  1. C.__class__.mro()
  2. >>>>
  3. [<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.Base'>, <class 'object'>]

可以看到,C 的下一个类是 A,于是,跳到了 A 的 init,这时会打印出 enter A,并执行下面一行代码:

  1. super(A,self).__init__()

注意,这里的 self 也是当前 C 的实例,MRO 列表跟上面是一样的,搜索 A 在 MRO 中的下一个类,发现是 B,于是,跳到了 B 的 init,这时会打印出 enter B,而不是 enter Base

Object类

  • Object类是所有类的父类,所有的类都包含object类的属性和方法
  • 内置函数dir()可以查看所有指定对象的属性
  • object类有一个内置的str()方法,用于返回一个对于对象的描述,对应内置函数str()经常 用print()进行重写
    1. Class Student:
    2. def __init__(self,name,age):
    3. self.name = name
    4. self.age = age
    5. def __str__(self):
    6. return '姓名:{0} 年龄:{1}'.format(self.name,self.age)
    7. stu1 = Student('张三',20)
    8. print(stu1)
    9. print(type(stu1))
    | 特殊属性名 | 作用 | 特殊方法 | 作用 | | | —- | —- | —- | —- | —- | | dict | 属性字典类的静态函数、类函数、普通函数、全局变量以及一些内置的属性都是放在类dict里的
    对象的dict中存储了一些self.xxx的一些东西
    | len() | | | | class | 对象所属的类 | add(self,other) | 相加运算 | s = stu1.add(stu1)
    任意2个对象相加 | | bases | 父类的元素 | new() | | 创建一个对象self | | base | 多态继承的第一个元素 | init() | 类的对象初始化 | 给 参数赋值,返回给实例对象 | | mro | 类的层次结构 | subclasses() | 子类的列表 | | | | | repr() | 会返回和调用者有关的 “类名+object at+内存地址”信息 | 方法返回一个实例的代码表示形式,通常用来重新构造这个实例。 | | | | str() | 输出对象变量:
    默认输出<__main__.Person object at 0x00000000026F90F0> | str() 方法将实例转换为一个字符串,使用 str() 或 print() 函数会输出这个字符串 |
  1. class A:
  2. pass
  3. class B:
  4. pass
  5. class C(A,B):
  6. def __init__(self,name,age):
  7. self.name = name
  8. self.age = age
  9. x = C('jack',20)
  10. print(x.__dict__) #实例对象的属性字典
  11. print(C.__dict__) #类对象的属性字典
  12. print(x.__class__) #实例对象所属的类
  13. print(C.__bases__) #父类的元素,返回元组
  14. print(C.__base__) #继承的第一个父类元素
  15. print(C.__mro__) #类的层次结构
  16. print(A.__subclasses__()) #子类的列表
  17. >>>{'name':'jack','age':20}
  18. >>>{'__module__':'__main__','__init__':<function C.__init__ at 0x00001c53432e>,'__doc__':None}
  19. >>><class '__main__.C'>
  20. >>>(<class '__main__.A'>,<class '__main__.B'>)
  21. >>><class '__main__.A'>
  22. >>>(<class '__main__.C'>,<class '__main__.A'>,<class '__main__.B'>,<class 'object'>)
  23. >>>[<class '__main__.C'>]
  1. class Student:
  2. def __init__(self,name):
  3. self.name = name
  4. def __add__(self,other):
  5. return self.name+other.name
  6. def __len__(self):
  7. return len(self.name)
  8. stu1 = Student('张三')
  9. stu2 = Student('李四')
  10. s = stu1+stu2
  11. print(s)
  12. print(stu1.__add__(stu2))
  13. print(stu2.__len__())
  14. >>> 张三李四
  15. >>> 张三李四
  16. >>> 2
  17. list1 = [1,2,3,4,5]
  18. print(list1.__len__())
  19. >>> 5
  1. class Singleton(object):
  2. def __new__(cls,*args,**kwargs):
  3. print('__new__被调用了,cls的值为{0}'.format(id(cls)))
  4. obj = super().__new__(cls)
  5. print('obj被创建的对象id为{0}'.format(id(obj)))
  6. return obj
  7. def __init__(self,name,age):
  8. print('__init__被调用了,self的值为{0}'.format(id(self)))
  9. self.name = name
  10. self.age = age
  11. print('obj这个类对象的id为{}'.format(id(object)))
  12. print('Singleton这个类对象的id为{}'.format(id(Singleton)))
  13. p1 = Singleton('李四',30)
  14. print('p1这个实例对象的id为:{0}'.format(id(p1)))
  15. >>obj 对象3232
  16. Singleton 对象9360
  17. __new__ cls 9360
  18. obj 7140
  19. self 7140
  20. p1 实例 7140
  1. 多态

    浅拷贝和深拷贝

  • 详细的说明 ```python import copy class cpu: pass class disk: pass class computer: def init(self,cpu,disk):
    1. self.cpu = cpu
    2. self.disk = disk
    cpu1 = cpu() cpu2 = cpu1 print(id(cpu1)) print(id(cpu2))

    8940 8940 disk1 = disk() computer1 = computer(cpu1,disk1)

    浅copy不copy类的子类

    computer2 = copy.copy(computer1) computer3 = copy.deepcopy(computer1) print(computer1,computer1.cpu,computer1.disk) print(computer2,computer2.cpu,computer2.disk)

    >

    computer1和computer2的内存地址不一样,但是子对象的内存地址是一样的

    computer1和computer3的子对象内存地址也不一样

    <__main__.computer object at 0x0000001781F3284C0>,<__main__.cpu object at 0x0000001781F3432CF21><__main__.disk object at 0x0000001781F34323FD2> <__main__.computer object at 0x0000001781F329180>,<__main__.cpu object at 0x0000001781F3432CF21><__main__.disk object at 0x0000001781F34323FD2> <__main__.computer object at 0x0000001781F3223F4>,<__main__.cpu object at 0x0000001781F3432FE32><__main__.disk object at 0x0000001781F343222E5>

```