- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
TL;DR -
我有一个使用元类的类。
我想在初始化过程之前从元类访问对象构造函数的参数,但我找不到访问这些参数的方法。
如何从元类函数__new__
访问构造函数的参数?
为了练习在Python中使用元类,我想创建一个类,用作《银河系漫游指南》一书中的 super 计算机“Deep Thought”。
我的类(class)的目的是存储 super 计算机从用户那里获得的各种查询。
最重要的是,它只会获取一些参数并存储它们。
如果给定的参数之一是数字 42 或字符串“生命、宇宙和一切的答案”,我不想创建一个新对象,而是返回一个指向现有对象的指针。
这背后的想法是,这些对象将完全相同,因此当使用 is
运算符比较这两个对象时,结果将为 true。
为了能够使用 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__
方法仅获取四个参数:
元类实例本身、类的名称、其基类及其属性。
如何将参数从构造函数发送到元类?
我可以做什么来实现我的目标?
最佳答案
您不需要元类。
事实是__init__
不是Python中对象的“构造函数”,而是通常称为“初始化器”。 __new__
更接近其他语言中“构造函数”的角色,并且它不仅仅适用于元类 - 所有类都有 __new__
方法。如果没有明确实现, object.__new__
直接调用。
实际上,它是 object.__new__
它在 Python 中创建一个新对象。从纯 Python 代码中,没有其他可能的方法来创建对象:它总是会经过那里。这意味着如果您实现 __new__
方法在您自己的类上,您可以选择不创建新实例,而是返回同一类(或任何其他对象)的另一个预先存在的实例。
您只需记住:如果 __new__
返回同一个类的实例,那么默认行为是 __init__
在同一个实例上调用。否则,__init__
没有被调用。
还值得注意的是,近年来,一些使用元类在 Python 中创建“单例”的方法变得流行 - 这实际上是一种过度杀伤的方法,这是压倒性的 __new__
也更适合创建单例。
在你的情况下,你只需要有一个字典,其中包含你想要跟踪的参数作为键,并检查是否创建一个新实例或每当 __new__
时“回收”一个实例。运行。字典可以是类属性,也可以是模块级别的全局变量 - 这是您的选择:
class Recycler:
_instances = {}
def __new__(cls, parameter1, ...):
if parameter1 in cls._instances:
return cls._instances[parameter1]
self = super().__new__(cls) # don't pass remaining parameters to object.__new__
_instances[parameter1] = self
return self
如果您在__init__
中有任何代码除此之外,将其移至 __new__
以及。
您可以拥有具有此行为的基类并拥有类层次结构,而无需重新实现 __new__
每堂课。
对于元类,当实际创建使用该元类创建的类的新实例时,不会调用它的任何方法。只有通过装饰或创建新的 __new__
自动插入此行为才有用。方法,在使用该元类创建的类上。由于此行为更容易跟踪、维护,并且总体上只需使用普通继承即可与其他类组合,因此根本不需要元类。
关于python - 从元类访问构造函数的参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48254371/
简而言之:我想从可变参数模板参数中提取各种选项,但不仅通过标签而且通过那些参数的索引,这些参数是未知的 标签。我喜欢 boost 中的方法(例如 heap 或 lockfree 策略),但想让它与 S
我可以对单元格中的 excel IF 语句提供一些帮助吗? 它在做什么? 对“BaselineAmount”进行了哪些评估? =IF(BaselineAmount, (Variance/Baselin
我正在使用以下方法: public async Task Save(Foo foo,out int param) { ....... MySqlParameter prmparamID
我正在使用 CodeGear RAD Studio IDE。 为了使用命令行参数测试我的应用程序,我多次使用了“运行 -> 参数”菜单中的“参数”字段。 但是每次我给它提供一个新值时,它都无法从“下拉
我已经为信用卡类编写了一些代码,粘贴在下面。我有一个接受上述变量的构造函数,并且正在研究一些方法将这些变量格式化为字符串,以便最终输出将类似于 号码:1234 5678 9012 3456 截止日期:
MySql IN 参数 - 在存储过程中使用时,VarChar IN 参数 val 是否需要单引号? 我已经像平常一样创建了经典 ASP 代码,但我没有更新该列。 我需要引用 VarChar 参数吗?
给出了下面的开始,但似乎不知道如何完成它。本质上,如果我调用 myTest([one, Two, Three], 2); 它应该返回元素 third。必须使用for循环来找到我的解决方案。 funct
将 1113355579999 作为参数传递时,该值在函数内部变为 959050335。 调用(main.c): printf("%d\n", FindCommonDigit(111335557999
这个问题在这里已经有了答案: Is Java "pass-by-reference" or "pass-by-value"? (92 个回答) 关闭9年前。 public class StackOve
我真的很困惑,当像 1 == scanf("%lg", &entry) 交换为 scanf("%lg", &entry) == 1 没有区别。我的实验书上说的是前者,而我觉得后者是可以理解的。 1 =
我正在尝试使用调用 SetupDiGetDeviceRegistryProperty 的函数使用德尔福 7。该调用来自示例函数 SetupEnumAvailableComPorts .它看起来像这样:
我需要在现有项目上实现一些事件的显示。我无法更改数据库结构。 在我的 Controller 中,我(从 ajax 请求)传递了一个时间戳,并且我需要显示之前的 8 个事件。因此,如果时间戳是(转换后)
rails 新手。按照多态关联的教程,我遇到了这个以在create 和destroy 中设置@client。 @client = Client.find(params[:client_id] || p
通过将 VM 参数设置为 -Xmx1024m,我能够通过 Eclipse 运行 Java 程序-Xms256M。现在我想通过 Windows 中的 .bat 文件运行相同的 Java 程序 (jar)
我有一个 Delphi DLL,它在被 Delphi 应用程序调用时工作并导出声明为的方法: Procedure ProduceOutput(request,inputs:widestring; va
浏览完文档和示例后,我还没有弄清楚 schema.yaml 文件中的参数到底用在哪里。 在此处使用 AWS 代码示例:https://github.com/aws-samples/aws-proton
程序参数: procedure get_user_profile ( i_attuid in ras_user.attuid%type, i_data_group in data_g
我有一个字符串作为参数传递给我的存储过程。 dim AgentString as String = " 'test1', 'test2', 'test3' " 我想在 IN 中使用该参数声明。 AND
这个问题已经有答案了: When should I use "this" in a class? (17 个回答) 已关闭 6 年前。 我运行了一些java代码,我看到了一些我不太明白的东西。为什么下
我输入 scroll(0,10,200,10);但是当它运行时,它会传递字符串“xxpos”或“yypos”,我确实在没有撇号的情况下尝试过,但它就是行不通。 scroll = function(xp
我是一名优秀的程序员,十分优秀!