在前面我们一起认识学习了Python面向对象基础,对面向对象的理论基础和Python基本的面向对象特性的有关知识已经了解,现在让我们深入的 了解 Python面向对象。
方法名首尾都有两个下划线的方法叫做 magic method,比如构造方法和析构方法。
1. 对象的实例化的魔术方法
创建类的对象(__new__)————>初始化对象(__init__)
构造对象的过程:
首先是调用__new__方法创建类的对象:def __new__(cls)(有返回),通常不必定义(Python3都会继承所属父类或者object类,父类会自动创建类的对象),返回一个类的初始对象
然后将返回的对象交给__init__,对属性进行设置:def __init__(self)
实例:
class Programer(object):
def __new__(cls, *args, **kwargs): #通过改写new方法,new方法必须设置return,完成所需功能
print( 'call __new__ method')
print(args)
return super(Programer, self).__new__(cls, *args, **kwargs) #object类takes no parameters(参数)
def __init__(self, name, age): #属性设置初始化
print('call __init__ method')
self.name = name
self.age = age
#Python有垃圾回收机制,会自动调用__del__()方法 ,不用定义
if __name__ = '__main__':
programer = Programer('Albert', 25) #会调用重写的__new__方法
print(programer.__dict__)
2. 类与运算符的魔术方法
比较运算符:
__cmp__(self,other):比较
__eq__(self,other):等于
__lt__(self,other):小于
__gt__(self,other):大于
__add__(self,other) : 加
__sub__(self,other) : 减
__mul__(self,other) : 乘
__div__(self,other) : 除
__or__(self,other) : 逻辑或
__and__(self,other) : 逻辑与
实例:
class Programer(object):
def __init__(self, name, age): #属性初始化设置
self.name = name
if isinstance(age, int):
self.age = age
else:
raise Exception('age must be int') #通过raise显式地引发异常。一旦执行了raise语句,raise后面的语句将不能执行。
def __eq__(self, other): #判断两个对象self和other是否相等,首先判断传进来的对象是不是同样的类型,isinstance(other,Programer),然后判断他们的属性是否相等
if isinstance(other, Programer):
if self.age == other.age:
return True
else:
return False
else:
raise Exception('the type of object must be Programer')
def __add__(self, other): #重写__add__方法,对两个对象的属性进行加运算
if isinstance(other, Programer):
return self.age + other.age
else:
raise Exception('the type of object must be Programer')
if __name__=='__main__':
p1 = Programer('Albert',25)
p2 = Programer('Bill',30)
print(p1==p2) #判断两个对象是否相等,首先判断传进来的对象是不是同样的类型,isinstance(other,Programer),然后判断他们的属性是否相等
print(p1+p2)
输出结果:
>>Flase
>>55
3. 类的展现的魔术方法
在print的过程中,将对象转换为字符串,包括三种方法:
__str__:转换成适合人看的字符串
__repr__:转换成适合机器看的字符串
__unicode__
展现对象属性:__dir__
实例:
class Programer(object):
def __init__(self, name, age):
self.name = name
if isinstance(age, int):
self.age = age
else:
raise Exception('age must be int')
def __str__(self):
return '%s is %s years old' % (self.name, self.age)
def __dir__(self):
return self.__dict__.keys()
if __name__ = '__main__':
p = Programer('Albert', 25)
print(p)
print dir(p)
将重写的__str__,__dir__方法注释掉,输出结果如下:
反之输出结果:
类的展现和属性的展现的目的,我们可以这样理解:用__str__可以直接print p就出来,但是自己构造方法的话需要print p.method()出来,至于__dir__可能有时候我们不需要打印所有属性,只选择需要的打印。
4. 类的属性控制
Python中的内置函数,不可以直接用于类,但是大部分可以通过简单的魔术方法进行定义,然后就可以直接调用了。
def __setattr__(self,name,value):
setattr(self,name,value)
错误的原因是会导致无限的循环,而Python只有循环1000次。
设置对象属性的方法 : 通常不必定义,类会自动调用从父类继承的方法
def \_\_setattr__(self, name, value):
self.\_\_dict__[name] = value
查询对象属性的方法:
__getattr__(self,name[, default]):获取对象的属性值(访问属性在默认情况下没有被查询到的时候才调用),default – 默认返回值,如果不提供该参数,在没有对应属性时,将触发 AttributeError
__getattribute__(self, name):每次访问属性一定会调用,容易引起无限递归,最好调用父类的getattribute
删除对象属性的方法:
__delattr__(self, name)
实例:
class Programer(object):
def __init__(self, name, age):
self.name = name
self.age = age
def __getattribute__(self,name):
# return getattr(self, name)
# return self.__dict__[name] #这两种都是错误写法,都会访问属性,会引起无限循环
return super(Programer, self).__getattribute__(name) #调用父类的getattribute,才不会无限递归
def __setattr__(self, name, value):
# setattr(self, key, value)会再调用__setattr__,所以会无限循环,是错误写法
self.__dict__[name] = value #正确写法
if __name__ = '__main__':
p = Programer('Albert', 25)
print(p.name)
输出结果:
——>>Albert
Python面向对象的相关知识到这里就告一段落了
写在最后,欢迎关注一个一起学python的微信公众号:大众学python
掏出手机扫一扫: