【发布时间】:2018-06-23 13:48:20
【问题描述】:
TL;DR -
我有一个使用元类的类。
我想在初始化过程之前从元类访问对象构造函数的参数,但我找不到访问这些参数的方法。
如何从元类访问构造函数的参数函数__new__?
为了练习在python中元类的使用,我想创建一个类,用作《银河系漫游指南》一书中的超级计算机“深度思考”。
我的课程的目的是存储超级计算机从用户那里获得的各种查询。
归根结底,它只会获取一些参数并存储它们。
如果给定的参数之一是数字 42 或字符串“生命、宇宙和一切的答案”,我不想创建一个新对象,而是返回一个指向现有对象的指针。
这背后的想法是这些对象将完全相同,因此当使用 is 运算符比较这两个时,结果将是正确的。
为了能够使用is 运算符并得到True 作为答案,我需要确保这些变量指向同一个对象。所以,为了返回一个指向现有对象的指针,我需要在对象的初始化过程中间进行干预。我无法检查构造函数本身的给定参数并相应地修改对象的内部变量,因为为时已晚:如果我仅将给定参数作为__init__ 函数的一部分进行检查,那么这两个对象将被分配在不同的部分内存(它们可能相等,但在使用 is 运算符时不会返回 True)。
我想过做这样的事情:
class SuperComputer(type):
answer = 42
def __new__(meta, name, bases, attributes):
# Check if args contains the number "42"
# or has the string "The answer to life, the universe, and everything"
# If so, just return a pointer to an existing object:
return SuperComputer.answer
# Else, just create the object as it is:
return super(SuperComputer, meta).__new__(meta, name, bases, attributes)
class Query(object):
__metaclass__ = SuperComputer
def __init__(self, *args, **kwargs):
self.args = args
for key, value in kwargs.items():
setattr(self, key, value)
def main():
number = Query(42)
string = Query("The answer to life, the universe, and everything")
other = Query("Sunny", "Sunday", 123)
num2 = Query(45)
print number is string # Should print True
print other is string # Should print False
print number is num2 # Should print False
if __name__ == '__main__':
main()
但我一直坚持从构造函数获取参数。
我看到__new__ 方法只有四个参数:
元类实例本身、类的名称、它的基类及其属性。
如何将参数从构造函数发送到元类?
我可以做些什么来实现我的目标?
【问题讨论】:
-
您试图在错误的地方进行检查。它需要在
Query.__new__中,而不是在SuperComputer.__new__中。你根本不需要元类。 -
我不明白你为什么需要一个元类。元类
__new__是在你定义classQuery时执行的,那时你似乎不想做任何事情。如果您想检查 Query 何时被实例化,只需在Query.__new__中进行检查。 -
所以在这种情况下我根本不需要使用
metaclass?我认为我需要这样做,因为这类似于(半)单例,因为它有时会返回相同的对象而不是创建新的对象,我看到实现这一目标的最佳方法是使用元类(stackoverflow.com/a/6798042/6253504 )。您能否详细说明一下,以便我了解有什么区别以及我可以做些什么不同的事情? -
使用元类远非创建单例的最佳方式。 (实际上,甚至在阅读此评论之前,我就在回答中提到了这一点)
标签: python python-2.7 oop instance metaclass