使用实例名访问实例变量

2024-10-01 05:01:57 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一门课是这样的:

Class PropertyExpr:
    def __init__(self, value, expr):
        self.value = value
        self.expr = expr

假设我像这样初始化类:

prop1 = PropertyExpr(5, "test")

我知道如果我想访问valueexpr,我会调用prop1.valueprop1.expr

但是,我希望这样,无论何时调用prop1,它都会自动返回prop1.valueprop1.expr仍然可以访问expr变量

由于value可以是任何数据类型,我认为使用__str__是行不通的

谢谢你的帮助

编辑:这是我当前的方法,但它只适用于int,我需要扩展它,以便它也适用于其他数据类型,例如list:

class PropertyExpr(int):

    def __new__(self, value: int, expr: Optional[str]=None, *args, **kwargs):
        return int.__new__(self, value, *args, **kwargs)

    def __init__(self, value: int, expr: Optional[str]=None, *args, **kwargs):
        int.__init__(value, *args, **kwargs)
        if expr is None:
            self.expr = str(value)
        else:
            self.expr = expr

因此,当我创建实例时:

prop1 = PropertyExpr(5, "test")

因此,当我使用prop1时,它将返回5和prop1.expr = "test"


Tags: testselfnonenewinitvaluedefargs
2条回答

您可以这样做:

class PropertyExpr(int):

    def __new__(cls, value, expr):
        obj = super().__new__(cls, value)
        obj.expr = expr
        return obj
 
var = PropertyExpr(5, "test")
print(var)
print(var.expr)

输出:

$ python3 so.py 
5
test

如果“call”实际上指的是call而不仅仅是“access”,那么您可以简单地实现一个__call__方法:

class PropertyExpr:
    def __init__(self, value, expr):
        self.value = value
        self.expr = expr

    def __call__(self):
        return self.value

prop1 = PropertyExpr(5, "test")

val = prop1()
print(val)

输出:

5

在这种情况下,调用prop1()的结果实际上可以是任何东西

除此之外,你想要的是不可能的。您可以重写__new__方法,但这也会更改所创建内容的类型。因此,如果您返回5,您的对象将是5,但它也将是int,不再是PropertyExpr的实例,并且所有附加属性都将丢失:

class PropertyExpr():
    def __new__(cls, value, expr):
        return value

    def __init__(self, value, expr):
        self.value = value
        self.expr = expr

prop1 = PropertyExpr(5, "test")

print(prop1, type(prop1))
try:
    print(prop1.expr)
except Exception as e:
    print(e)

输出:

5 <class 'int'>
'int' object has no attribute 'expr'

经过一些尝试,我找到了一种动态更改构造函数类型的方法,但是我建议不要实际使用:

class PropertyExpr:
    def __new__(cls, tp, value, *args, **kwargs):
        return type("FakeType", (tp,), kwargs)(value)

prop1 = PropertyExpr(int, 5, expr="expr int")
print(prop1, " -> ", prop1.expr)

prop2 = PropertyExpr(list, "5", expr="expr list")
print(prop2, " -> ", prop2.expr)

prop3 = PropertyExpr(str, "abc", expr="expr string")
print(prop3, " -> ", prop3.expr)

输出:

5  ->  expr int     
['5']  ->  expr list
abc  ->  expr string

您可以将希望子类的类型作为第一个参数传递,第二个参数应该是该类型的构造函数接受的值,然后您可以传递任意KWARG,这些KWARG将作为属性添加到创建的对象中


is there a way to make is so that type(prop1) would still be PropertyExpr? Edit: for example, if we can do isinstance(prop1, PropertyExpr) = True then everything would be perfect

我不能让它工作(这并不意味着其他人不能),但我设法使它与多重继承一起工作,因此您可以使用isinstance(prop1, PropertyExprMixin)

class PropertyExprMixin:
    pass

class PropertyExpr:
    def __new__(cls, tp, value, *args, **kwargs):
        return type("PropertyExprMixin", (tp,PropertyExprMixin), kwargs)(value)

prop1 = PropertyExpr(int, 5, expr="expr int")
print(prop1, " -> ", prop1.expr, type(prop1), isinstance(prop1, int), isinstance(prop1, PropertyExprMixin))

prop2 = PropertyExpr(list, "5", expr="expr list")
print(prop2, " -> ", prop2.expr, type(prop2), isinstance(prop2, list), isinstance(prop2, PropertyExprMixin))

prop3 = PropertyExpr(str, "abc", expr="expr string")
print(prop3, " -> ", prop3.expr, type(prop3), isinstance(prop3, str), isinstance(prop3, PropertyExprMixin))

输出:

5  ->  expr int <class '__main__.PropertyExprMixin'> True True     
['5']  ->  expr list <class '__main__.PropertyExprMixin'> True True
abc  ->  expr string <class '__main__.PropertyExprMixin'> True True

相关问题 更多 >