类
类的组成
class Student:
native_place = '吉林' #类属性
__type = 'Person' #类的私有属性
def __init__(self,name,age): #name ,age为实例属性
self.name = name
self.age = age
#实例方法
def info(self):
print("my name is %s,my age is %s" % (self.name,self.age))
#类方法 当方法中需要使用类对象 (如访问私有类属性等)时,定义类方法可以获取
@classmethod
def get_type(cls):
print('类方法')
return cls.__type
#静态方法 静态方法不会自动传递实例对象和类对象
@staticmethod
def sm():
print('静态方法')
类的对象
stu = Student('Jack',30) #创建一个实例对象
stu.info() #调用实例方法
print(stu.name) #实例属性
print(stu.age) #实例属性
print(stu.native_place) #类属性
#动态改变类属性
Student.native_place = '天津'
print(stu.native_place) #输出为天津
类方法和静态方法
当方法中 既不需要使用实例对象(如实例对象,实例属性),也不需要使用类对象 (如类属性、类方法、创建实例等)时,定义静态方法
取消不需要的参数传递,有利于 减少不必要的内存占用和性能消耗
Student.get_type()
>>Person
Student.sm()
>>静态方法
三大特性
- 封装
将数据的属性和行为包装到类对象中,python中如果要使用私有属性或者类,在前面使用’__’
class Student:
def __init__(self,name,age):
self.name = name
self.__age = age
def show(self):
print('这个学生的名字是%s ,年龄是%d' %(self.name,self.__age))
stu1 = Student('张三',20)
print(stu1.show())
print(stu1.name)
print(stu1.__age)
print(stu1._Student__age) 可以这样输出 私有属性
- 继承
Class Person:
def __init__(self,name,age):
self.name = name
self.age = age
def info(self):
print('姓名:{0} 年龄:{1}'.format(self.name,self.age))
Class Student(Person):
def __init__(self,name,age,score):
super().__init__(name,age)
self.score=score
def info(self):
super().info()
print('成绩:{0}'.format(self.score))
Class Teacher(Person):
def __init__(self,name,age,year):
super().__init__(name,age) #继承父类的方法和属性
self.year = year
stu1 = Student('李四',30,100)
stu1.info() #方法重写了,调用子类的方法
teacher = Teacher('张梅',40,'初三')
teacher.info() #直接使用父类的方法
super()的方法
class Base(object):
def __init__(self):
print("enter Base")
print("leave Base")
class A(Base):
def __init__(self):
print("enter A")
super(A,self).__init__()
print("leave A")
class B(Base):
def __init__(self):
print("enter B")
super(B,self).__init__()
print("leave B")
class C(A,B):
def __init__(self):
print("enter C")
super(C,self).__init__()
print("leave C")
c = C()
>>>>
enter C
enter A
enter B
enter Base
leave Base
leave B
leave A
leave C
MRO列表:
事实上,对于你定义的每一个类,Python 会计算出一个方法解析顺序(Method Resolution Order, MRO)列表,它代表了类继承的顺序,我们可以使用下面的方式获得某个类的 MRO 列表。这个列表真实的列出了类C的继承顺序。C->A->B->Base->object。在方法调用时,是按照这个顺序查找的。
那这个 MRO 列表的顺序是怎么定的呢,它是通过一个 C3 线性化算法来实现的,这里我们就不去深究这个算法了,感兴趣的读者可以自己去了解一下,总的来说,一个类的 MRO 列表就是合并所有父类的 MRO 列表,并遵循以下三条原则:
- 子类永远在父类前面
- 如果有多个父类,会根据它们在列表中的顺序被检查
如果对下一个类存在两个合法的选择,选择第一个父类
def super(cls, inst):
mro = inst.__class__.mro()
return mro[mro.index(cls) + 1]
其中,cls 代表类,inst 代表实例,上面的代码做了两件事
获取 inst 的 MRO 列表
- 查找 cls 在当前 MRO 列表中的 index, 并返回它的下一个类,即 mro[index + 1]
这里的 self 是当前 C 的实例,self.class.mro() 结果是
C.__class__.mro()
>>>>
[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.Base'>, <class 'object'>]
可以看到,C 的下一个类是 A,于是,跳到了 A 的 init,这时会打印出 enter A,并执行下面一行代码:
super(A,self).__init__()
注意,这里的 self 也是当前 C 的实例,MRO 列表跟上面是一样的,搜索 A 在 MRO 中的下一个类,发现是 B,于是,跳到了 B 的 init,这时会打印出 enter B,而不是 enter Base
Object类
- Object类是所有类的父类,所有的类都包含object类的属性和方法
- 内置函数dir()可以查看所有指定对象的属性
- object类有一个内置的str()方法,用于返回一个对于对象的描述,对应内置函数str()经常 用print()进行重写
| 特殊属性名 | 作用 | 特殊方法 | 作用 | | | —- | —- | —- | —- | —- | | dict | 属性字典类的静态函数、类函数、普通函数、全局变量以及一些内置的属性都是放在类dict里的Class Student:
def __init__(self,name,age):
self.name = name
self.age = age
def __str__(self):
return '姓名:{0} 年龄:{1}'.format(self.name,self.age)
stu1 = Student('张三',20)
print(stu1)
print(type(stu1))
对象的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() 函数会输出这个字符串 |
class A:
pass
class B:
pass
class C(A,B):
def __init__(self,name,age):
self.name = name
self.age = age
x = C('jack',20)
print(x.__dict__) #实例对象的属性字典
print(C.__dict__) #类对象的属性字典
print(x.__class__) #实例对象所属的类
print(C.__bases__) #父类的元素,返回元组
print(C.__base__) #继承的第一个父类元素
print(C.__mro__) #类的层次结构
print(A.__subclasses__()) #子类的列表
>>>{'name':'jack','age':20}
>>>{'__module__':'__main__','__init__':<function C.__init__ at 0x00001c53432e>,'__doc__':None}
>>><class '__main__.C'>
>>>(<class '__main__.A'>,<class '__main__.B'>)
>>><class '__main__.A'>
>>>(<class '__main__.C'>,<class '__main__.A'>,<class '__main__.B'>,<class 'object'>)
>>>[<class '__main__.C'>]
class Student:
def __init__(self,name):
self.name = name
def __add__(self,other):
return self.name+other.name
def __len__(self):
return len(self.name)
stu1 = Student('张三')
stu2 = Student('李四')
s = stu1+stu2
print(s)
print(stu1.__add__(stu2))
print(stu2.__len__())
>>> 张三李四
>>> 张三李四
>>> 2
list1 = [1,2,3,4,5]
print(list1.__len__())
>>> 5
class Singleton(object):
def __new__(cls,*args,**kwargs):
print('__new__被调用了,cls的值为{0}'.format(id(cls)))
obj = super().__new__(cls)
print('obj被创建的对象id为{0}'.format(id(obj)))
return obj
def __init__(self,name,age):
print('__init__被调用了,self的值为{0}'.format(id(self)))
self.name = name
self.age = age
print('obj这个类对象的id为{}'.format(id(object)))
print('Singleton这个类对象的id为{}'.format(id(Singleton)))
p1 = Singleton('李四',30)
print('p1这个实例对象的id为:{0}'.format(id(p1)))
>>obj 对象3232
Singleton 对象9360
__new__ cls 9360
obj 7140
self 7140
p1 实例 7140
- 详细的说明
```python
import copy
class cpu:
pass
class disk:
pass
class computer:
def init(self,cpu,disk):
cpu1 = cpu() cpu2 = cpu1 print(id(cpu1)) print(id(cpu2))self.cpu = cpu
self.disk = disk
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>
```