python魔法方法详解_Python魔术方法详解

写这个的初衷主要是因为网上充斥的大量的假冒伪劣解释说明

好歹自己试一试再写文章啊! 真的是误人子弟

例如: __ getattr__:获取一个不存在的属性时调用的方法 事实上获取任何属性的时候都会调用这个方法(包括存在和不存在的属性)

1. __init __ 和 __new __

__init__(self)

这个方法是一个对象方法,它主要是用来构建对象属性的

当对象创建的时候,就需要给这个对象赋予属性 这个时候,这个对象就开始自动调用了

by tokiea (简书)

class A:

def __init__(self):

print('开始给对象赋予属性了')

a = A()

__________________________________

`开始给对象赋予属性了`

def __new__(cls, *args, **kwargs):

这个方法是一个类方法,它用来创建对象的

也就是对象创建的时候最先调用的方法

通常会用来做单例模式和对象创建计数

*args, **kwargs是用来接收和传递创建对象时的参数

by tokiea (简书)

class A:

def __init__(self, name, age=1): # 实例方法

print('开始给对象赋予属性了')

self.name = name

self.age = age

def __new__(cls, *args, **kwargs): # 类方法

print('开始新建对象了')

print('我是参数args', args)

print('我是参数kwargs', kwargs)

return object.__new__(cls)

# 必须要有返回值 返回创建出来的实例

a = A('小明', age=2)

__________________________________

`开始新建对象了`

`我是参数args ('小明',)`

`我是参数kwargs {'age': 2}`

`开始给对象赋予属性了`

2.__ getattr__ 和 __ setattr__

很好理解的字面意思

获取属性和设置属性时调用的方法

__getattr__(self, item)

当获取实例化后的对象属性时,会自动调用的方法,好像除了阻止别人直接获取属性之外没特别大的用处了

用了这个方法之后,所有的实例对象属性都是需要在这里返回的,否则就是None值

by tokiea (简书)

7bd64e3dea91

class A:

def __init__(self, name, age=1):

self.name = name # 我想多凑几个字数

self.age = age

def __getattr__(self, item):

print('报告老大,有人在调用我的属性', item)

if item =='name':

return '不告诉你'

a = A('小明', age=2)

print(a.name)

print(a.age)

__________________________________

`报告老大,有人在调用我的属性 name`

`不告诉你`

`报告老大,有人在调用我的属性 age`

`None`

__setattr__(self, key, value):

这个方法比__getattr __要好用一些

设置属性的时候调用(当然初始化的时候也会调用一次)

可以用来判断属性设置的值(也可以改变即将设置的属性值)

by tokiea (简书)

class A:

def __init__(self, name):

self.name = name # 我想多凑几个字数

self.age = 1

def __setattr__(self, key, value):

print('开始给实例对象赋值了', key, value)

if key == 'age' and value:

# 这个可以做判断或者改变赋值的操作

if isinstance(value, int):

pass

else:

print('赋值错误,请填整数类型')

a = A('小明')

a.age = 10

a.age = '十八'

__________________________________

`开始给实例对象赋值了 name 小明`

`开始给实例对象赋值了 age 1`

`开始给实例对象赋值了 age 10`

`开始给实例对象赋值了 age 十八`

`赋值错误,请填整数类型`

3. __ enter __和 __ exit __

__enter__(self)

__exit__(self, exc_type, exc_val, exc_tb)

这两个方法就是用with的时候使用的,上下文管理

而且是 都要有

否则就会报错,差不多就像干将和莫邪,杨过和大雕,缺一不可

三个参数:

exc_type 错误类型

exc_val 错误原因

exc_tb 错误发生的内存地址

by tokiea (简书)

class A:

def __init__(self, name):

self.name = name # 我想多凑几个字数

self.age = 1

def __enter__(self):

print('我要进去了,嘿嘿嘿')

def __exit__(self, exc_type, exc_val, exc_tb):

print(exc_type)

print(exc_val)

print(exc_tb)

print('我要出去了')

a = A('小明')

with a:

print('我进来了')

a.age = 1/0 # 0不能做被除数 会报错

__________________________________

`Traceback (most recent call last):`

`我要进去了,嘿嘿嘿`

`我进来了`

`File ".....................py", line 18, in `

`a.age = 1/0`

`ZeroDivisionError: division by zero`

``

`division by zero`

``

`我要出去了`

4. __del __

__del__(self)

就是被删除的时候调用的方法

python自带垃圾回收 当对象没有引用的时候就会自动触发垃圾回收 自动调用 __del __ 方法

by tokiea (简书)

class A:

def __del__(self):

print('啊!我被删除了')

a = A()

del a # 这句 可有可无 因为程序运行结束会自动触发

__________________________________

`啊!我被删除了`

PS 刚好看研究了一下描述符 也写一点吧

__get __ , __set __ 和 __delete __

__get__(self, instance, owner)

看参数 instance 实例 owner 拥有者 就知道一个是拥有者 一个是被拥有 肯定需要两个对象

class A:

def __get__(self, instance, owner):

print('A:我被(实例)%s调用了,它属于 %s 类'%(instance,owner))

class B:

a = A()

b=B()

B.a

b.a

__________________________________

`A:我被(实例)None调用了,它属于 类`

`A:我被(实例)<__main__.B object at 0x0000028F0BC00CC0>调用了,它属于 类`

__set__(self, instance, value)

参数 一个是实例 一个是值

class A:

def __set__(self, instance, value):

print('我是A:我监听到了:%s被实例:%s设置成了属性' % (value, instance))

class B:

pass

a = A()

b = B()

B.a = a # 把实例对象a 先赋值给 类对象B 的类属性 a

b.a = 12345 # 再把 12345 赋值给实例对象b 的a

print(B.a)

print(b.a)

__________________________________

`我是A:我监听到了:12345被实例:<__main__.B object at 0x0000016923F90CC0>设置成了属性`

`<__main__.A object at 0x0000016923F90C88>`

`<__main__.A object at 0x0000016923F90C88>`

最后发现不管是实例对象b 还是类对象B 它们的a属性都是a实例 即使实例b进行了重新赋值12345的操作,也没能改变实例b的a属性

我想知道为什么 求教大佬

by tokiea (简书)

7bd64e3dea91

__delete__(self, instance)

class A:

def __delete__(self, instance):

print('实例对象%s把我删除了'%instance)

class B:

pass

a = A()

b = B()

B.a = a # 把实例对象a 先赋值给 类对象B 的类属性 a

b.a = 12345 # 再把 12345 赋值给实例对象b 的a

del b.a

print(b.a)

__________________________________

`实例对象<__main__.B object at 0x0000029510180CC0>把我删除了`

`<__main__.A object at 0x0000029510180C88>`

发现最后a实例没有被b实例删除 而是只调用了a的__delete __方法

by tokiea (简书)

未完待续 -- tokiea

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值