python - 覆盖父命名空间变量
问题描述
在深入研究元类之前,我试图了解 Python 类。我遇到了一些我无法弄清楚的代码。在这种情况下,类不使用self而是使用类名称空间(没有使用 self 的选项,因此这里的问题)。如何在一个类中定义一些命名空间变量,然后在子类中覆盖它们都依赖的值?
第一个案例
class B():
potato = "hey"
test = potato
#here would go a lot of more code that just depends on that potato value
class c(B):
B.potato = "not hey"
c_potato = c().test
print(c_potato)
它打印嘿。我理解是因为test指向字符串“hey”,它是不可变的。更改B.potato = "not hey"
只会将类命名空间土豆更改为新字符串,但不会更改测试指向的内容。所以我想,嘿,如果我用一个列表来做,那是通过引用来做的吗?
class B():
potato = ["hey"]
test = potato[0]
class c(B):
B.potato[0] = "not hey"
c_potato = c().test
print(c_potato)
在我看来,这应该有效。我没有改变土豆指向的东西,而是改变了价值。不?但我知道它实际上不会起作用,因为test指向的是potato[0]而不是只是potato。所以是的,我明白为什么这也会打印hey。
那时我意识到,如果测试需要指向不可变的结果,那么我试图用命名空间做的事情是不可能的。
class B():
@staticmethod
def get_potato():
return "hey"
potato = get_potato.__func__
test = potato()
class c(B):
@staticmethod
def get_potato():
return "not hey"
B.potato = "6"
c_potato = c().test
print(c_potato)
我在这里更改了B.potato的整个值,但现在test已经指向父母的结果potato(),所以没关系,仍然打印出"hey"。
然后我想,元类可以解决这个问题吗?显然是的,它可以。
class Meta(type):
def __new__(cls, name, bases, attrs):
x = super().__new__(cls, name, bases, attrs)
x.potato = "basic hey"
if 'meta_args' in attrs:
x.potato = attrs['meta_args'][0]
del attrs['meta_args'] # clean up
x.test = x.potato
return x
class A():
pass
class B(A, metaclass=Meta):
meta_args = ["super hey"]
pass
class C(B):
meta_args = ["not hey"]
b = B().test
c = C().test
print(b)
print(c)
并且正确打印super hey fo b而不是 hey for c。问题是,这可以在没有元类的情况下完成吗?此时我的大脑很痛。
解决方案
你可能想要一个@property
:
class B:
potato = 'hey'
@property
def test(self):
return self.potato
class C(B):
potato = 'not hey'
你所做的是以一种或另一种方式分配"hey"
给的。test
除非您实际上将其他内容分配给test
. 通过将其设为 a ,每次访问时都会调用@property
该函数,因此可以动态计算其值;在这种情况下,基于 的值。子类声明了自己的,它隐藏了父类的属性。def test
.test
potato
potato
potato
推荐阅读
- c++ - #包括
失败,#include "Eigen/Dense" 成功 - 为什么? - php - 在 Magento2 中创建新页面时出现“php_network_getaddresses: getaddrinfo failed: Name or service not known”错误
- asp.net - ASP .net 中的 curl 请求返回 400 错误请求
- google-bigquery - 运行 BigQuery 的 DDL“ALTER TABLE ADD COLUMN”是否收费?
- html - 如何在 HTML 中创建预期的按钮?
- twitter-bootstrap - 带有滚动内容的 Bootstrap 5 固定高度容器
- matlab - 如何在 matlab 中将 2-D 单元阵列转换为 3-D 单元阵列
- java - 动作不能转换为类 java.lang.String
- autodesk-forge - 如何解释来自 Forge Automation API 的此错误消息?
- android - 当我使用风味时,如何构建原始版本/调试版本?有没有办法为每种口味创建文件夹?& 一次构建所有类型?