python面向对象之魔法方法

Python面向对象之魔法方法

一、简介

python==3.7; 2020-04-12
python 类中,使用左右双下划线的预定义方法。当对对象做某种操作时,会触发魔法方法的调用, 是程序员与Python解释器交互的接口.

二、几个基本的魔法方法

# 构造函数
## __new__(cls,)与 __init__(self,);实例化对象时, new最先被调用, 然后是init被调用;以下使用__new__来实现单例。
class Constant():
    def __new__(cls,*args, **kwargs):
        print(f"__new__ 被调用 -- {cls}")
        if not hasattr(cls, "is_instanced"):
            cls.is_instanced = super(Constant, cls).__new__(cls)
        return cls.is_instanced
            
    def __init__(self, password):
        print(f"__init__ 被调用 -- {self}")
        self.password = password
        
constant = Constant("123456")
print(constant, Constant)
print(constant.password)
constant = Constant("111111")
print(constant, Constant)
print(constant.password)
__new__ 被调用 -- <class '__main__.Constant'>
__init__ 被调用 -- <__main__.Constant object at 0x0000027CA719D908>
<__main__.Constant object at 0x0000027CA719D908> <class '__main__.Constant'>
123456
__new__ 被调用 -- <class '__main__.Constant'>
__init__ 被调用 -- <__main__.Constant object at 0x0000027CA719D908>
<__main__.Constant object at 0x0000027CA719D908> <class '__main__.Constant'>
111111
# 析构函数
# __del__(), 当删除对象时,被调用
class A():
    def __init__(self):
        print("init")
    
    def close(self):
        print("close")
        
    def __del__(self):
        print("析构函数被调用")
        self.close() # 对象被删除之前做点事情

a = A()
# del a # 主动删除 a 变量, 或者Python垃圾回收机制删除也会被调用
print("end")
init
析构函数被调用
close
end
# __call__() 将对象当做函数调用
class Fibonacci():
    """
    斐波那契数列1
    """
    def __call__(self, n):
        self.a = 1
        self.b = 1
        self.c = 2
        if n <= 2:
            return 1
        else:
            for i in range(n-2):
                self.c = self.a + self.b
                self.a, self.b = self.b, self.c
        return self.c
fibonacci = Fibonacci()
for i in range(1,11):
    print(fibonacci(i), end = " ")
1 1 2 3 5 8 13 21 34 55 
# __str__() 当使用print(obj) 时调用的方法, 或者强制转换为 str 类型时调用
class Student():
    def __init__(self, name, age):
        self.name = name
        self.age = age
        
    def __str__(self):
        return f"name: {self.name}, age: {self.age}"
    
class Test(): # 没有重写__str
    name = "Test"
    
tesla = Student("Tesla", 18)
print(tesla)
temp = str(tesla) + f" --- {tesla}"
print(temp)
test = Test()
print(test) # 没有重写 __str__ 函数 返回类名,和id
name: Tesla, age: 18
name: Tesla, age: 18 --- name: Tesla, age: 18
<__main__.Test object at 0x0000027CA7657988>
# __dict__ __doc__ 两个属性
class A():
    "test doc"
    name = "name"

a = A()
a.age = 18
print(a.__dict__, a.__doc__)
析构函数被调用
close
{'age': 18} test doc

三、 对象属性相关的魔法方法

# 对象属性相关的魔法方法
# __getattr__(self, name), __getattribute__(self, name), __setattr__(self, name, value), __delattr__(self, name)

class Constant():
    def __getattr__(self, name):
        print("getattr", name)
    
    def __getattribute__(self, name):
        print("getattribute")
        return super().__getattribute__(name) # 调用基类方法获取name的value
        
    def __setattr__(self, name, value):
        print("setattr: ", name, value)
        super().__setattr__(name, value + "--赋值前做点处理")
    
    def __delattr__(self, name):
        print("delattr")
        super().__delattr__(name)
        
constant = Constant()
constant.user = "Tesla"
print("打印 user: ", constant.user)
del constant.user
print("打印 user: ", constant.user)
setattr:  user Tesla
getattribute
打印 user:  Tesla--赋值前做点处理
delattr
getattribute
getattr user
打印 user:  None

四、容器相关的魔法方法

# 容器对象相关的魔法方法
# __len__(self), __getitem__(self, key), __setitem__(self, key, value), __delitem__(self, key), __iter__(self), __reversed__(self), 
# __contains__(self, item), __next__() 
class Fibonacci():
    """
    Fibonacci2 生成、存储斐波那契数列
    """
    def __init__(self, n=20, a=1, b=1):
        self.length = n
        self.list = [a,b]
        self.i = 0
        # 生成斐波那契数列装进list中
        for each in range(n-2):
            temp = a + b
            a, b = b, temp
            self.list.append(temp)
        self.a = a
        self.b = b
    def __setitem__(self, key, value):
        if key==0:
            self.a = value
        elif key==1:
            self.b = value
        else:
            print("仅支持给index=0,1 赋值")
            return None
        
        a = self.a
        b = self.b
        self.list = [self.a, self.b]

        for each in range(self.length-2):
            temp = a + b
            a, b = b, temp
            self.list.append(temp)
            
    def __getitem__(self, key):
        if isinstance(key, int):
            return self.list[key]
        elif isinstance(key, slice):
            # slice对象有三个属性,start,stop,step
            start = key.start
            stop = key.stop
            step = key.step
            return self.list[start:stop:step]
    
    def __delitem__(self, key):
        print("不支持del")
        
    def __iter__(self):
        return self
    
    def __next__(self):
        if 0 <= self.i < self.length:
            temp = self.list[self.i]
            self.i +=1
            return temp
        else:
            self.i = 0
            raise StopIteration
    
    def __contains__(self, item):
        return item in self.list
    
    def __reversed__(self):
        # 调用 reversed(obj)的行为
        return self.list[::-1]
    
    def __str__(self):
        string = ""
        for each in self.list:
            string += f", {each}"
        return string[2:]
    
    def __len__(self):
        return self.length
    
fibonacci = Fibonacci(10)
print(fibonacci)
fibonacci[0] = 1
fibonacci[1] = 2
fibonacci[2] = 3
del fibonacci[1]
print(fibonacci)
print("切片:", fibonacci[::-1])
a = sorted(fibonacci)
b = reversed(fibonacci)
print("sorted:", a)
print("reversed:", b)
print(2 in fibonacci)
print(2 not in fibonacci)

for each in fibonacci:
    print(each)
1, 1, 2, 3, 5, 8, 13, 21, 34, 55
仅支持给index=0,1 赋值
不支持del
1, 2, 3, 5, 8, 13, 21, 34, 55, 89
切片: [89, 55, 34, 21, 13, 8, 5, 3, 2, 1]
sorted: [1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
reversed: [89, 55, 34, 21, 13, 8, 5, 3, 2, 1]
True
False
1
2
3
5
8
13
21
34
55
89

五、 算数操作相关的魔法方法

# 算数操作的魔法方法
# 二元操作符
# __add__(), __sub__(), __mul__(), __truediv__(), __flordiv__(), __mod__(), __divmod__(), __pow__(), 
# __lshift__(), __rshift__(), __and__(),  __xor__(), __or__()
# 一元操作符
# __neg__(), __pos__(), __abs__(), __invert__()

class Matrix():
    """矩阵简单运算"""
    def __init__(self, value):
        self.value = value
        self.shape = (len(value),len(value[0]))
        for each in value:
            if len(each) != len(value[0]):
                raise TypeError("类型错误")
            
    def __add__(self, other):
        if other.shape != self.shape:
            raise TypeError("不同shape矩阵不能相加")
        
        result = []
        for i in range(self.shape[0]):
            temp = []
            if self.shape[0] > 0:
                for j in range(self.shape[1]):
                     temp.append(self.value[i][j] + other.value[i][j])
            else:
                temp = self.value[i] + other.value[i]
                
            result.append(temp) 
            
        return Matrix(result)
    
    def __sub__(self, other):
        if other.shape != self.shape:
            raise TypeError("不同shape矩阵不能相加")
        
        result = []
        for i in range(self.shape[0]):
            temp = []
            if self.shape[1] > 0:
                for j in range(self.shape[1]):
                     temp.append(self.value[i][j] - other.value[i][j])
            else:
                temp = self.value[i] - other.value[i]
                
            result.append(temp) 
        # print(result)
        return Matrix(result)
    
    def __mul__(self, other):
        print(other)
        if other.shape != self.shape:
            raise TypeError("不同shape矩阵不能相加")
        
        result = []
        add = 0
        for i in range(self.shape[0]):
            temp = []
            if self.shape[1] > 0:
                for j in range(self.shape[1]):
                    add2 = 0
                    for k in range(self.shape[1]):
                        add2 += (self.value[i][k] * other.value[k][j])
                    temp.append(add2)
                result.append(temp) 
            else:
                add += self.value[i] * other.value[i]
        
        result = add if self.shape[1] <=0 else result
        return Matrix(result)
    
    def __str__(self):
        string = ""
        for each in self.value:
            string += f"{each}\n"
        return string
a = Matrix([[1,2],[3,4]])
b = Matrix([[1,1],[1,1]])
c = a + b
print(a,b)
print(c, type(c))
print(a - b)
print(a * b)
[1, 2]
[3, 4]
 [1, 1]
[1, 1]

[2, 3]
[4, 5]
 <class '__main__.Matrix'>
[0, 1]
[2, 3]

[1, 1]
[1, 1]

[3, 3]
[7, 7]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值