Python - 在调用时转换 class 属性
Python - Transform class attributes at call time
假设我有以下 class
class Headings:
standard_heading = {
'height': 3.72,
'width': 25.68,
'left': 1.65,
'top': 0.28
}
例如,我想要以下所有值都乘以 10 的结果:
Headings.standard_heading
>>> {
'height': 37.2,
'width': 256.8,
'left': 16.5,
'top': 2.8
}
有没有办法通过向 class 添加类似于此的方法来覆盖对 class 属性的调用:
def __getattribute__(cls, attr):
return {k:v*10 for k,v in attr.items()
我永远不会创建此 class 的实例。我只是将它用于分组目的。
谢谢
如果您想将此行为应用于许多不同的 class,您可以创建一个父 class。
class MultiplyBy10:
def __getattribute__(self, attr):
return {k:v*10 for k,v in super().__getattribute__(attr).items()}
class Headings(MultiplyBy10):
standard_heading = {
'height': 3.72,
'width': 25.68,
'left': 1.65,
'top': 0.28
}
h = Headings()
print(h.standard_heading)
会显示
{'height': 37.2, 'width': 256.8, 'left': 16.5, 'top': 2.8000000000000003}
如果您的要求是更改从您的字典返回的值,而不是创建另一个字典,您可能想要构建一个自定义字典 - :How to "perfectly" override a dict?
你几乎搞定了 - 只需将 getter 定义为 class 方法(还有一个小语法错误,attr
在这里是一个字符串):
class Headings:
standard_heading = {
'height': 3.72,
'width': 25.68,
'left': 1.65,
'top': 0.28
}
@classmethod
def __getattribute__(cls,attr):
return {k:v*10 for k,v in cls.__dict__[attr].items()}
print(Headings().standard_heading)
请注意,您确实需要一个实际实例才能正常工作,但这就是您在示例中使用的实例。这也会破坏在对象的任何方法中定义的对象特定字段的 get 属性(例如 __init__
),所以要小心。一个简单的解决方法是同时覆盖:
@classmethod
def __getattribute__(cls,attr):
try:
return {k:v*10 for k,v in cls.__dict__[attr].items()}
except: raise AttributeError(attr)
def __getattr__(self,attr):
return object.__getattribute__(self,attr)
所以现在如果你有:
def __init__(self): self.a = 'abc'
然后
print(Headings().a)
也可以。解释:
- 首先
__getattribute__
被称为 class 方法。
- 如果不存在 class 变量,则
__getattr__
被调用,现在作为常规方法,因此使用实际对象(和对象成员)。
- 调用
object
__getattribute__
返回正常行为。
最后一点 - 除了你的具体问题,如果你只想为一个 class 成员定义一个特殊的 getter
,一种只会影响所述成员的更安全的方法是使用 @property
和 @getter
- 正如在 How does the @property decorator work?. Thanks Adonis 中指出的那样。
假设我有以下 class
class Headings:
standard_heading = {
'height': 3.72,
'width': 25.68,
'left': 1.65,
'top': 0.28
}
例如,我想要以下所有值都乘以 10 的结果:
Headings.standard_heading
>>> {
'height': 37.2,
'width': 256.8,
'left': 16.5,
'top': 2.8
}
有没有办法通过向 class 添加类似于此的方法来覆盖对 class 属性的调用:
def __getattribute__(cls, attr):
return {k:v*10 for k,v in attr.items()
我永远不会创建此 class 的实例。我只是将它用于分组目的。
谢谢
如果您想将此行为应用于许多不同的 class,您可以创建一个父 class。
class MultiplyBy10:
def __getattribute__(self, attr):
return {k:v*10 for k,v in super().__getattribute__(attr).items()}
class Headings(MultiplyBy10):
standard_heading = {
'height': 3.72,
'width': 25.68,
'left': 1.65,
'top': 0.28
}
h = Headings()
print(h.standard_heading)
会显示
{'height': 37.2, 'width': 256.8, 'left': 16.5, 'top': 2.8000000000000003}
如果您的要求是更改从您的字典返回的值,而不是创建另一个字典,您可能想要构建一个自定义字典 - :How to "perfectly" override a dict?
你几乎搞定了 - 只需将 getter 定义为 class 方法(还有一个小语法错误,attr
在这里是一个字符串):
class Headings:
standard_heading = {
'height': 3.72,
'width': 25.68,
'left': 1.65,
'top': 0.28
}
@classmethod
def __getattribute__(cls,attr):
return {k:v*10 for k,v in cls.__dict__[attr].items()}
print(Headings().standard_heading)
请注意,您确实需要一个实际实例才能正常工作,但这就是您在示例中使用的实例。这也会破坏在对象的任何方法中定义的对象特定字段的 get 属性(例如 __init__
),所以要小心。一个简单的解决方法是同时覆盖:
@classmethod
def __getattribute__(cls,attr):
try:
return {k:v*10 for k,v in cls.__dict__[attr].items()}
except: raise AttributeError(attr)
def __getattr__(self,attr):
return object.__getattribute__(self,attr)
所以现在如果你有:
def __init__(self): self.a = 'abc'
然后
print(Headings().a)
也可以。解释:
- 首先
__getattribute__
被称为 class 方法。 - 如果不存在 class 变量,则
__getattr__
被调用,现在作为常规方法,因此使用实际对象(和对象成员)。 - 调用
object
__getattribute__
返回正常行为。
最后一点 - 除了你的具体问题,如果你只想为一个 class 成员定义一个特殊的 getter
,一种只会影响所述成员的更安全的方法是使用 @property
和 @getter
- 正如在 How does the @property decorator work?. Thanks Adonis 中指出的那样。