在 Python 对象中,需要重写的双下划线开头和结尾的属性称为特殊属性,另外以双下划线开头和结尾的方法称为特殊方法
特殊属性:__name__,__dict__等
特殊方法:__init__,__str__等
常见的特殊属性和特殊方法:
源代码先写出来
1、特殊属性
(1)__dict__ :获取类对象或实例对象所绑定的所有属性和方法,以字典的形式输出
(2) __class__:获取实例对象所属的类
(3)__bases__:获取类对象的父类元组(以元组形式输出)
(4)__base__:获取类对象的第一个父类(class 类对象后面的()里先写谁就输出谁)
(5)__mro__:获取类的层次结构 在搞不清楚类和类之间的继承关系时可以用它来查看
(6)__subclasses__():获取所查看类所具有的子类
class A:
pass
class B:
pass
class C(A,B):
def __init__(self,name,type):
self.name=name
self.type=type
class D(A):
pass
x=C('王大锤','搞笑')
print(x.__dict__) #查看对象的属性(实例对象)的属性字典,以字典的形式输出
print(C.__dict__) #查看这个类方法的属性和方法的字典
'''实例对象查看的只有属性,类对象是方法和属性都能看到'''
#{'name': '王大锤', 'type': '搞笑'}
#'__module__': '__main__', '__init__': <function C.__init__ at 0x01DE4810>, '__doc__': None}
print(x.__class__) #查看x这个实例对象所属的类 <class '__main__.C'>
print(C.__bases__) #查看类对象的父类(以元组形式输出 可能会有多个父类(这里会涉及到多继承问题))
#(<class '__main__.A'>, <class '__main__.B'>)
print(C.__base__) #<class '__main__.A'>
print(C.__mro__) #查看C的层次结构 #(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
'''C继承了A和B,又继承了object'''
print(A.__subclasses__()) #查看该类的子类,以列表的形式输出 [<class '__main__.C'>, <class '__main__.D'>]
2、特殊方法
(1)__add__()方法:通过重写方法使得自定义的对象有加法功能
先举一个两个整数型数据相加的例子
a=20
b=30
c=a+b
print(c) #结果是50
但再实际的底层运算中,是调用了a对象的__add__()方法与b对象进行了加法运算
s=a.__add__(b)
print(s) #结果也是50
两者的结果都是一样的,一个是表面看到的,另一个是在底层逻辑中的运算方法
不光是数字数据型的数据可以进行加法运算,我自己自定义的对象(类对象)也可以进行加法运算,就是通过__add__方法来实现
class Students:
def __init__(self,name,age):
self.name=name
self.age=age
def __add__(self, other):
return self.name+other.name #如果非要让两个自定义对象相加,就用__add__()方法这样写
stu1=Students('小红',14)
stu2=Students('小白',16)
plus=stu1+stu2
print(plus)
如果在一个类对象中使用了__add__()方法重写,则在最后进行的加法运算中程序只会执行这多个__add__()方法中的最后一个
若在一个__add__()方法中有多个返回值,则程序只执行第一个return/print
class Students:
def __init__(self,name,age):
self.name=name
self.age=age
def __add__(self, other):
return self.name+other.name #如果非要让两个自定义对象相加,就用__add__()方法这样写
def __add__(self,score):
return self.age+score.age
'''如果在类中使用了多个__add__()方法,则程序只会执行这多个__add__()方法中的最后一个'''
stu1=Students('小红',14)
stu2=Students('小白',16)
plus=stu1+stu2
print(plus) #结果是30
如果没有使用__add__()方法而直接让两个实例对象相加,程序会返回错误(不支持这样类型的数据相加),说明这样加法的的话不可行
class Students:
def __init__(self,name,age):
self.name=name
self.age=age
stu1=Students('小红',14)
stu2=Students('小白',16)
plus=stu1+stu2
print(plus)
结果:TypeError: unsupported operand type(s) for +: 'Students' and 'Students'
(2)__len__()方法:对应的是内置函数len()方法,通过len方法可以使自定义对象也可以输出长度
list=[11,22,33,44]
print(len(list))
print(list.__len__()) #结果使一样的,说明他俩作用相同
class Students:
def __init__(self,name,age):
self.name=name
self.age=age
def __len__(self):
return len(self.name)
stu1=Students('小红',14)
print(len(stu1)) #结果为2
(3)__new__()方发:创建对象
(4)__init__()方法:对创建的对象进行初始化
class Person(object):
def __new__(cls, *args, **kwargs): # __new__方法用于创建对象
print('__new__方法被调用执行了,cls的id值为{0}'.format(id(cls)))
result=super().__new__(cls) #因为Person继承的object,想调用父类的__new__方法来看一下
print('创建的对象的id值为{0}'.format(id(result)))
return result
def __init__(self,name,height):
print('__init__方法被调用执行了,self的id值为{0}'.format(id(self)))
self.name=name
self.height=height
print('object这个类对象的id值为{0}'.format(id(object)))
print('Person这个类对象的id值为{0}'.format(id(Person)))
#创建Person类的实例对象
p1=Person('王大锤',175)
print('p1这个Person类的实例对象的id值为{0}'.format(id(p1)))
object这个类对象的id值为1760188064
Person这个类对象的id值为12024168
__new__方法被调用执行了,cls的id值为12024168
创建的对象的id值为11798704
__init__方法被调用执行了,self的id值为11798704
p1这个Person类的实例对象的id值为11798704
'''从结果中能看出来,上面__new__方法中所创建的对象(引用父类object的__new__方法创建的对象)
就是__init__方法中的self和实例对象p1'''
具体的代码运行过程分析见下图: