在前面我们一起认识学习了Python面向对象基础,对面向对象的理论基础和Python基本的面向对象特性的有关知识已经了解,现在让我们深入的 了解 Python面向对象。

一、Python Maigc Method (魔术方法)

方法名首尾都有两个下划线的方法叫做 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__)

输出结果:

python面向对象简答题 python面向对象编程题目_Python

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__方法注释掉,输出结果如下:

python面向对象简答题 python面向对象编程题目_深入Python面向对象_02


反之输出结果:

python面向对象简答题 python面向对象编程题目_面向对象_03

类的展现和属性的展现的目的,我们可以这样理解:用__str__可以直接print p就出来,但是自己构造方法的话需要print p.method()出来,至于__dir__可能有时候我们不需要打印所有属性,只选择需要的打印。

4. 类的属性控制

Python中的内置函数,不可以直接用于类,但是大部分可以通过简单的魔术方法进行定义,然后就可以直接调用了。

def __setattr__(self,name,value):

setattr(self,name,value)

错误的原因是会导致无限的循环,而Python只有循环1000次。

python面向对象简答题 python面向对象编程题目_python面向对象简答题_04

设置对象属性的方法 : 通常不必定义,类会自动调用从父类继承的方法

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面向对象的相关知识到这里就告一段落了