可以在 Python 的类中调用有状态函数吗?
Posted
技术标签:
【中文标题】可以在 Python 的类中调用有状态函数吗?【英文标题】:Possible to call stateful function in a class in Python? 【发布时间】:2020-09-17 08:28:02 【问题描述】:是否可以在 Python 中直接设置某个值并通过任何方式(继承、元类、类装饰器)在类中获取它? B类不能被A中的set('a')污染。
import sys
class A:
set('a')
get()
# -> 'a'
print(sys.modules[__name__])
# => <module '__main__'>
class B:
get()
# -> None
【问题讨论】:
set
和 get
到底在做什么?
对于A
类,set('a')
将A
类(但不是它的实例)的'a'
保存到内存中。 get()
从内存中获取保存的'a'
。它不必在get
ting 时从内存中删除'a'
。如果set()
被调用两次,第一个值将被第二个值覆盖。在 B 中,get()
尝试获取为类 B
保存的任何值。但是,它没有任何价值。因为,set()
没有在 B
中调用。
这告诉我你想要他们做什么;我问他们实际上在做什么:显示定义。
实际上,set
和 get
做什么是任意的。但是,假设他们所做的会影响 Python 中答案的实现方式,这是一个示例; ``` a = 无;默认设置(值):a = 值; def get(): 返回一个; ``` 但是,这个例子显然不适用于我的第一个例子。这能回答你的问题吗?
set
正在创建一个局部变量;它不会更改全局变量 a
或 A
的类属性的值。
【参考方案1】:
这两个独立的类不相互引用,所以只要你不将同一个对象传递给它们,那么它们都不会“污染”另一个。要设置一个值并获取一个对象的值,你可以使用这样的东西:
class A:
def __init__(self):
self.letter = None
def set_value(self, letter):
self.letter = letter
def get_value(self):
return self.letter if self.letter else '(none set)'
class B:
def __init__(self):
self.letter = None
def set_value(self, letter):
self.letter = letter
def get_value(self):
return self.letter if self.letter else '(none set)'
>>> a = A()
>>> aa = A()
>>> b = B()
>>> a.set_value('z')
>>> print(f'values in a, aa, and b are: a.get_value(), aa.get_value(), b.get_value()')
values in a, aa, and b are: z, (none set), (none set)
如您所见,设置a
对象的字母不会将其设置在b
(不同的类)或aa
中,后者是同一个A 类的不同实例。希望对您有所帮助!
编码愉快!
【讨论】:
不幸的是,这与我要求的不同。我想要一个等价物而不创建 A 和 B 的实例。 不幸的是,我无法真正说出您的要求。您可以在一个类上获取和设置值,并且它不会被另一个类污染。 “设置一个特定的值并以任何方式将它放在一个类中”并不提供信息。设置一个值并再次取回它并不复杂,所以我认为你可能只是缺少一些关于你需要的细节的额外细节。随意添加更多的问题。 我的代码告诉我我想要什么......元编程和实例级编程是两个非常不同的方案。请查看您的代码是否适用于我的代码。还是谢谢【参考方案2】:假设您知道自己在做什么,是的,可以在类主体中使用编程名称设置值,然后检索,并将这些值限制在该类主体中。
您所要做的就是使用locals()
调用来获取命名空间字典,并使用该字典来保存您的值:
class A:
locals()["key"] = "a"
print(locals()["key"] )
这将打印“a”, 显然,这个值不会是 B 类命名空间的一部分。
如果您只想存储值而不关联,那么
有一个名字,stackfull
项目提供了一个
push
和 pop
调用的行为就像
你在你的例子中提出 -
但是如果您尝试使用pop()
而不是以前的push
在同一范围内,您将收到一个错误,原因是
堆栈下溢:
In [4]: !pip install stackfull
Collecting stackfull
...
Successfully installed stackfull-1.0.0
In [5]: from stackfull import push, pop
In [6]: class A:
...: push("a")
...: push("b")
...: print(pop())
...: print(pop())
...:
b
a
In [7]: class B:
...: pop()
...:
...
StackUnderflowError:
(免责声明 - 我是 stackfull 包的作者。我从来不需要 除了已经存在的内容之外的任何内容,因此很长时间没有更新 - 并且使用 Python 3.8 中的“海象”运算符,它不再那么有用)
好的 - 所以我列出了这个,因为它类似于您问题中的代码,但您可能需要更主流的东西,例如在方法中编写代码,并设置实例属性。
【讨论】:
非常感谢。我从您的建议中提出了一些实现想法:) 在您建议的第一个示例中,locals()["key"]
的分配值在我的情况下将是您可能期望的函数。您是否通过更新本地人提出任何副作用?我要做的一件事是它可以覆盖类主体中的现有函数。以上是关于可以在 Python 的类中调用有状态函数吗?的主要内容,如果未能解决你的问题,请参考以下文章