<p>如果“call”实际上指的是call而不仅仅是“access”,那么您可以简单地实现一个<code>__call__</code>方法:</p>
<pre><code>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)
</code></pre>
<p>输出:</p>
<pre><code>5
</code></pre>
<p>在这种情况下,调用<code>prop1()</code>的结果实际上可以是任何东西</p>
<p>除此之外,你想要的是不可能的。您可以重写<code>__new__</code>方法,但这也会更改所创建内容的类型。因此,如果您返回<code>5</code>,您的对象将是<code>5</code>,但它也将是<code>int</code>,不再是<code>PropertyExpr</code>的实例,并且所有附加属性都将丢失:</p>
<pre><code>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)
</code></pre>
<p>输出:</p>
<pre><code>5 <class 'int'>
'int' object has no attribute 'expr'
</code></pre>
<hr/>
<p>经过一些尝试,我找到了一种动态更改构造函数类型的方法,但是我建议不要实际使用:</p>
<pre><code>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)
</code></pre>
<p>输出:</p>
<pre><code>5 -> expr int
['5'] -> expr list
abc -> expr string
</code></pre>
<p>您可以将希望子类的类型作为第一个参数传递,第二个参数应该是该类型的构造函数接受的值,然后您可以传递任意KWARG,这些KWARG将作为属性添加到创建的对象中</p>
<hr/>
<blockquote>
<p>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</p>
</blockquote>
<p>我不能让它工作(这并不意味着其他人不能),但我设法使它与多重继承一起工作,因此您可以使用<code>isinstance(prop1, PropertyExprMixin)</code>:</p>
<pre><code>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))
</code></pre>
<p>输出:</p>
<pre><code>5 -> expr int <class '__main__.PropertyExprMixin'> True True
['5'] -> expr list <class '__main__.PropertyExprMixin'> True True
abc -> expr string <class '__main__.PropertyExprMixin'> True True
</code></pre>