Skip to main content
 首页 » 编程设计

python之如何区分类内和类外使用 __setattr__ 设置的属性

2025年05月04日15bonelee

在 __setattr__() 中有什么方法可以区分来自类或子/继承类内部的属性集,以及来自当前类或子类外部的属性集?

我想从“外部”更改设置属性的工作方式,在我制作模块的情况下,我希望用户在设置属性时与在类内部设置属性时具有不同的逻辑。

例如:
i.x = 5 当从类中调用时通常应该分配 5 并且 i 是它的一个实例,但是当从另一个类中调用时它应该减去 5 而不是设置为 5。

请您参考如下方法:

有点低级,但你可以使用 inspect 模块:

import inspect 
 
class A: 
 
    def __init__(self): 
        self.__x = 0 
 
    @property 
    def x(self): 
        return self.__x 
 
    @x.setter 
    def x(self, value): 
        f = inspect.currentframe() 
        if 'self' in f.f_back.f_locals and issubclass(type(f.f_back.f_locals['self']), A): 
            print('Called from class!') 
            self.__x = -value 
        else: 
            print('Called from outside!') 
            self.__x = value 
 
    def fn(self): 
        print('Calling A.x from inside:') 
        self.x = 10 
 
class B(A): 
    def __init__(self): 
        super().__init__() 
 
    def fn2(self): 
        print('Calling B.x from inside:') 
        self.x = 15 
 
a = A() 
print("A.x after init:", a.x) 
print('Calling A.x from outside') 
a.x = 10 
print("A.x called from the outside:", a.x) 
a.fn() 
print("A.x called from the inside:", a.x) 
 
b = B() 
print("B.x after init:", b.x) 
print('Calling B.x from outside') 
b.x = 20 
print("B.x called from the outside:", b.x) 
b.fn2() 
print("B.x called from the inside:", b.x) 

打印:

A.x after init: 0 
Calling A.x from outside 
Called from outside! 
A.x called from the outside: 10 
Calling A.x from inside: 
Called from class! 
A.x called from the inside: -10 
B.x after init: 0 
Calling B.x from outside 
Called from outside! 
B.x called from the outside: 20 
Calling B.x from inside: 
Called from class! 
B.x called from the inside: -15