python hasattar(),getattr(),setattr(), __getattr__(),__setattr__()的使用

声明:这里所说的类实例就是初始化一个类,然后建一个对象如:
a = A();
类对象,是类本身,因为类也是一个对象。

hasattar()

判断某个属性是否存在于某个类的属性集合中(包括函数,函数也是属性),如果不是,则返回false。
以下代码为例,我们初始化A的对象时,给所有的A的实例分配了一个属性value,每个实例都有此属性,只是不共享(注意,这不是类对象的属性,类对象的属性对类的实例来说,是全局变量)。那么,我们可以利用hasattar()判断一个属性是不是在一个对象属性的集合中。

class A(object):
    def __init__(self, value):
        self.value = value

    def __getattr__(self, item):
        print("找不到此属性")
        return super().__getattribute__(item)

a = A(10)
print(hasattr(a,"value"))
#结果为True

通过代码判断,value确实是属于A的某一个实例的属性,结果为True。假如,我们把value改成value1呢?通过代码判断,value1并不是A实例的属性。从代码中可以看出,调用hasattr()时,会自动调用__getattr__()去访问A实例的属性,如果类实例没有这个属性,就会返回False。

class A(object):
    def __init__(self, value):
        self.value = value

    def __getattr__(self, item):
        print("找不到此属性")
        return super().__getattribute__(item)

a = A(10)
print(hasattr(a,"value1"))

结果为:

找不到此属性
False

事实上我们不仅可以在hasattr()函数中的第一个参数放入类实例,也可以放类对象,因为类也是一个对象,或者说,类也是它上层类的一个实例(注意,这里说的上层类不是父类)。那么自然而然就可以放类对象。但是我们不能把hasattr()函数的第二个参数放类实例的属性,因为实例的属性只属于类实例,而不属于类对象,对类型对应的属性对类实例来说,是全局变量。

class A(object):
    name = "小明"
    def __init__(self, value):
        self.value = value
       

    def __getattr__(self, item):
        print("找不到此属性")
        return super().__getattribute__(item)

a = A(10)
print(hasattr(a,"value"))
print(hasattr(A,"value"))
print(hasattr(A,"name"))

结果为:

True
False
True

从结果可以得知,第二个结果为False,说明前面说的“实例的属性只属于类实例,而不属于类对象,对类型对应的属性对类实例来说,是全局变量”这句话是对的。有人可能奇怪,为什么“print(“找不到此属性”)”对应的这个函数为什么不执行,找不到属性的话,不是会执行__getattr__()函数吗?当然会执行,只不过执行的是A对象上层类的__getattr__()函数。

getattr()

获取某个对象的属性值,如果获取不到,则执行__getattr__函数抛出异常。

class A(object):
    name = "小明"
    def __init__(self, value):
        self.value = value
        self.key = "key"

    def __getattr__(self, item):
        print("找不到此属性")
        return super().__getattribute__(item)

    def test(self):
        print("哈哈")
        return "正在测试中"

a = A(10)

print(getattr(a,"key"))
#结果为:10

稍微该一行代码:

print(getattr(a,"key1"))

key1属性肯定不存在于类实例中的,结果会报错:

找不到此属性
Traceback (most recent call last):
  File "C:/Users/Administrator/Desktop/pm2/pm2/app1/tests.py", line 17, in <module>
    print(getattr(a,"key1"))
  File "C:/Users/Administrator/Desktop/pm2/pm2/app1/tests.py", line 9, in __getattr__
    return super().__getattribute__(item)
AttributeError: 'A' object has no attribute 'key1'

我们还可以对print(getattr(a,“key1”))这一行代码进行改造
那就是加一个默认值,print(getattr(a,“key1”,“我是默认值”)),
如果实例中没有“key1"这个属性,getattr()就会返回这个默认值,防止程序报错。

那我们把第二个参数传递为函数属性呢?同样可以获取函数属性的值,即函数地址。如果向执行的话,加个()括号调用下就行了。

print(getattr(a,"test1","我是默认值"))

结果为:

<bound method A.test of <__main__.A object at 0x00000280976408C8>

加上括号后:

print(getattr(a,"test1","我是默认值")())

结果为:

哈哈
正在测试

setattr函数

稍微修改以下源代码:

class A(object):
    name = "小明"
    def __init__(self, value):
        self.value = value
        self.key = "key"

    def __setattr__(self, key, value):
        self.__dict__[key] = value


    def test(self):
        print("哈哈")
        return "正在测试中"

a = A(10)

setattr(a,"key","我是修改后的key")
print(a.key)
#执行结果:我是修改后的key

当试图对象的item特性赋值的时,_setattr()将会被调用。
__setattr__依赖setattr()而存在。(其实也可以理解为,一个类实例就是一个字典,属性为”key“,值为"value",其实就是修改这个字典的key所对应的值)


给对象的属性赋值,若属性不存在,则先创建再赋值

```python
class A(object):
    name = "小明"
    def __init__(self, value):
        self.value = value
        self.key = "key"

    def __setattr__(self, key, value):
        self.__dict__[key] = value
        print("__setattr__被调用")


    def test(self):
        print("哈哈")
        return "正在测试中"

a = A(10)
setattr(a,"new_key","我是新建立的key")
print(a.new_key)

结果为:

__setattr__被调用
__setattr__被调用
__setattr__被调用
我是新建立的key

前两个”__setattr__被调用“是因为__init__函数里有两次赋值行为,会默认子弟哦那个调用__setattr__方法,最后一个才是因为”setattr(a,“new_key”,“我是新建立的key”)“这句代码。

通过setattr()\进行属性赋值和通过对象.属性=xxx进行赋值或者修改并无区别,都会调用__setattr__方法,可以结合字典的用法,无非就是增删查改,事实上,和字典用法并无实质区别(也可以结合《流畅的python》这本书,看一下,如何将字典模拟成类进行,然后进行类似于类的操作):

class A(object):
    # name = "小明"
    def __init__(self, value):
        self.value = value
        self.key = "key"


    def __setattr__(self, key, value):
        self.__dict__[key] = value
        print("__setattr__被调用")


    def test(self):
        print("哈哈")
        return "正在测试中"

a = A(10)
setattr(a,"new_key","我是新建立的key")
print(a.new_key)
a.new_key=2

结果为:

__setattr__被调用
我是新建立的key
__setattr__被调用

__setattr__和__getattr__结合之前的setattr和getattr的用法看一下

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
和__getattribute__函数是什么?它们的作用是什么? __getattr__是Python中的一个特殊方法,用于在访问一个不存在的属性时触发。当我们尝试访问一个对象的属性,而该属性不存在时,Python会调用__getattr__方法来处理这个请求。可以在__getattr__方法中自定义对不存在属性的处理逻辑,比如返回默认值或抛出异常。 __setattr__是Python中的另一个特殊方法,用于在给对象的属性赋值时触发。当我们对一个对象的属性进行赋值时,Python会调用__setattr__方法来处理这个赋值操作。可以在__setattr__方法中自定义对属性赋值的行为,比如进行一些额外的操作或进行属性值的验证。需要注意的是,在__setattr__方法中对属性进行赋值时,应该调用父类的__setattr__方法来避免引起无限递归。 __getattribute__是Python中的另一个特殊方法,用于获取对象的属性值。当我们尝试获取一个对象的属性时,不论这个属性是否存在,Python都会调用__getattribute__方法来处理这个请求。可以在__getattribute__方法中自定义对属性的获取行为,比如进行一些额外的操作或返回特定的属性值。需要注意的是,在__getattribute__方法内部访问属性时,应该使用super().__getattribute__方法来避免引起无限递归。 总结一下: - __getattr__用于处理访问不存在属性的情况,可以自定义对不存在属性的处理逻辑。 - __setattr__用于处理属性赋值的情况,可以自定义对属性赋值的行为。 - __getattribute__用于获取属性的值,可以自定义对属性获取的行为。 参考资料: 属性相关:__getattr__函数、__setattr__函数、__getattribute__函数、__setattribute__函数和__dir__函数: - 知乎 (zhihu.com) 引用中的代码示例。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值