python面向对象问题

来源:互联网 发布:守望先锋性能数据 ping 编辑:程序博客网 时间:2024/06/06 01:10

#1、__new__() // 实例化对象调用第一个方法并不是__init__而是__new__,一般Python默认调用, 一般只有在继承了不可变的类要去修改里面内容,需要重写#eg:class CapStr(str):    def __new__(cls, string):        string = string.upper()        return str.__new__(cls, string)#调用:cap = CapStr('aa')print(cap) # AA#2、__init__() // 构造方法不能有任何返回#3、__del__() // 对象将要被销毁,会自动被调用,跟php中的_destroy ,垃圾回收机制,当所有对象引用都被删除,才会调用#eg:class YO:    def __init__(self):        print('111')    def __del__(self):       print('22')#调用:yo = YO()yo1 = yodel yo # 此时不会调用__del__del yo1 # 两个都删掉才会调用__del__#22#4、算数运算#4.1正向运算class New_int(int):    def __add__(self, other):        return int.__sub__(self, other)    def __sub__(self, other):        return int.__add__(self, other)a = New_int(2)b = New_int(3)print(a + b)  # -1print(a - b)  # 5#4.2逆向运算class New_int(int):    def __radd__(self, other):        return int.__sub__(self, other)a = 3b = New_int(2)print(a + b)  # -1,因为3不是New_int,找不到,就会执行b的逆向运算radd,self是b,other是a#5、__setattr__()、__getattr()#__、__getattribute()#__、__delattr__()#__setattr__():对象给属性赋值会调用此方法#__getattribute__():读取对象属性调用此方法(不管属性是否存在都会调用)#__getattr__():对象属性不存在才会调用,此方法在__getattribute__()之后调用#__delattr__():删除一个对象的属性,调用此方法class MyTime:    def __setattr__(self, name, val):        print('setattr')        return super().__setattr__(name, val)    def __getattribute__(self, name):        print('getattribute')        return super().__getattribute__(name)    def __getattr__(self, name):        print('getattr')    def __delattr__(self, name):        print('delattr')        return super().__delattr__(name)m = MyTime()print(m.a)m.a = 2print(m.a)del m.a#6、描述符__get__ 、__set__、__delete__#6.1实例一:class MyProperty:    def __init__(self, fget=None, fset=None, fdel=None):        self.fget = fget        self.fset = fset        self.fdel = fdel    def __set__(self, instance, val):        self.fset(instance, val)    def __get__(self, instance, owener):        return self.fget(instance)    def __delete__(self, instance):        self.fdel(instance)class C:    def __init__(self):        self._x = 0    def getContent(self):        return self._x    def setContent(self, val):        self._x = val    def delContent(self):        del self._x    x = MyProperty(getContent, setContent, delContent)c = C()print(c.x)c.x = 11print(c.x)#6.2实例二:class A:    def __init__(self, value=0):        self.value = value    def __set__(self, instance, val):        self.value = val    def __get__(self, instance, owener):        return self.valueclass B:    def __init__(self, value=0):        self.value = value    def __set__(self, instance, val):        instance.a = val + 1    def __get__(self, instance, owener):        return instance.aclass C:    a = A()    b = B()c = C()print(c.a)c.a = 11print(c.a)c.b = 10print(c.a)print(c.b)#7、定制序列class Test:    def __init__(self, *args):        self.values = [x for x in args]        self.count = {}.fromkeys(range(len(self.values)), 0)    def __len__(self):        return len(self.count)    def __getitem__(self, key):        self.count[key] += 1        return self.values[key]t = Test(1, 2, 3, 4, 5, 6)print(t[1])print(t[2])print(t[1])print(t.count)#8 类属性与实例属性:实例对象属性优先级高于类对象属性,当类对象与实例对象属性相同的时候,通过对象调用该属性会优先调用对象中的,如果对象中没有此属性才会调用类中的属性class Test():    count = 0t1 = Test()t1.count = 10t2 = Test()t3 =Test()print(t1.count,t2.count,t3.count)#10 0 0del t1.countprint(t1.count,t2.count,t3.count)#0 0 0#9 正常情况下可以给该实例、类绑定任何属性和方法,但是可以使用__slots__限制只允许绑定哪些属性、方法from types import MethodTypeclass Test():    passt = Test()#9.1给实例绑定属性t.name = '张三'print(t.name) #张三#9.2给实例绑定方法,【注】:给一个实例绑定方法,其他实例无法使用,但是给类绑定方法所有实例都可以使用from types import MethodTypedef setAge(self, age):    self.age = ageclass Test():    passt = Test()t.setAge = MethodType(setAge,t)t.setAge(12)print(t.age) #12#9.3给类绑定方法from types import MethodTypedef setAge(self, age):    self.age = ageclass Test():    passTest.setAge = MethodType(setAge, Test)t = Test()t.setAge(12)print(t.age) #12#9.4 使用__slots__限制允许绑定的属性与方法class Test():    __slots__ = ('age','name')t = Test()t.age=12print(t.age)t.name = '张三'print(t.name)t.score = 21  #__slots__限制只能绑定age、name,当绑定score时就报错了,__slots__仅仅对当前类起作用,对子类不起作用#10 @property、@方法.setter,将方法变为外部可以调用属性class Test():    @property  # 将get方法变为属性访问    def name(self):        return self.__name    @name.setter  # 将set方法变为实行设值    def name(self, name):        if(len(name) > 4):            raise ValueError('超出字符长度')        self.__name = namet = Test()t.name = '张三'print(t.name)#张三#11 mixin设计混合,通过多继承特性实现类似java接口多个功能混合作用的一种设计,java、php这种单继承无法实现mixin,但可以类似Interfaceclass A(BMixin,CMixin): #这样A就有了BMixin、CMixin相关功能,避免单一继承    pass;#12 定制类#12.1 __slots__限制绑定属性、方法,__len__(),当调用len(obj)会触发obj.__len()__,除了这两个还有很多定制方法class Student():    def __init__(self,name):        self.name='张三'    def __str__(self):        return 'Student object(name:%s)' % self.name    __repr__ = __str__ #最懒得方法,不需要在重新定义一次#12.2、__str__print(Student('张三'))  #Student object(name:张三),触发__str__方法#2、__repr__s = Student('张三')s #交互模式下直接输入,不是出发__str__,而是出发__repr__()#12.3、__iter__class Fib(object):    def __init__(self):        self.a,self.b = 0,1    def __iter__(self):        return self #实例本身就是迭代对象,故返回自己    def __next__(self):        self.a,self.b = self.b,self.a+self.b        if self.a > 100000:            raise StopIteration        return self.a #下一个返回值#调用:for n in Fib():    print(n) #1 1 2 3 5...#__iter__()方法返回一个迭代对象,然后python的for循环就会不断调用该迭代对象的__next__()方法拿到循环的下一个值,直到StopIterration停止#12.4、__getitem__,虽然Fib()能循环想list一样,但不能像list一样用下标输出数据,如:Fib()[2],想要下表取出数据,就要有__getitem__class Fib():    def __getitem__(self, item):        a,b = 1,1        for x in range(n):            a,b = b,a+b        return af = Fib()print(f[0]) #1print(f[2]) #2#但是list有切片list(range(1,100)[5:30]),对于Fib()却报错。原因是__getitem__()传入的参数可能是一个int,也可能是一个切片对象slice,所以要判断:class Fib(object):    def __getitem__(self, item):        if isinstance(item,int):            a, b = 1, 1            for x in range(n):                a, b = b, a + b            return a        if isinstance(item,slice):            start = item.start            stop = item.stop            if start is None:                start = 0            a,b = 1,1            L = []            for x in range(stop):                if x >= start:                    L.append(a)                a,b = b,a+b            return Lf = Fib()print(f[0:5])#但是还没有对step步长做处理,还有__setitem__()、__delitem__()与之对应设置、删除,后续自己补充#12.5、__getattr__:正常情况下调用类的方法或者属性,不存在就报错,当调用不存在的属性时,python解释器会试图调用__getattr__class Student(object):    def __init__(self):        self.name = 'Michael'    def __getattr__(self, attr):        if attr == 'score':            return 99        else:            raise AttributeError('%s属性不存在' % attr)s = Student()print(s.name) #Michaelprint(s.age) #属性不存在#12.6、__call__():直接对实例进行调用class Student(object):    def __init__(self,name):        self.name = name    def __call__(self):        print('My name is %s.' % self.name)#调用:s = Student('Michael')s() #My name is Michael.