【问题标题】:Best python way to return the initializing value of class if of that same class如果是同一类,则返回类的初始化值的最佳python方法
【发布时间】:2016-07-25 14:48:37
【问题描述】:

我有一个类,我希望它接受同一个类的实例作为初始化;在这种情况下,它只会返回那个实例。

原因是我希望这个类接受无数的初始化值,然后后续代码可以将其用作具有已知属性的对象,而与它的初始化方式无关。

我想到了类似的东西:

class c(object):
  def __new__(cls, *args, **kwargs):
    if isinstance(args[0], c):
      return args[0]
    else:
      return super(c, cls).__new__(cls, *args, **kwargs)

问题是我不希望__init__() 在以这种方式初始化时被调用。有没有其他办法?

谢谢!

【问题讨论】:

  • 为什么不希望__init__() 被调用?如果__init__() 被调用,但没有做任何事情,会好吗?
  • __init__() 应仅在 args[0] 不属于该类时调用
  • 是的,您已经在问题中说明了这一点。但我问你:为什么这很重要?避免来电有多重要?您可以轻松地使调用在使用实例初始化时不执行任何操作,或者在使用其他值进行初始化时执行某些操作。
  • 嗯,你是对的......出于某种原因,起初它看起来不太像pythonic,无法在两个不同的函数中检查两次if 子句,但它看起来比工厂或初始化更好在__new__ 中,并且比元分类更简单。谢谢大家!

标签: python class oop initialization


【解决方案1】:

您可能想使用工厂(例如,请参阅question 了解详细信息或谷歌)。 或者只是使用你想要的类方法,f.e.:

class C(object):
    @classmethod
    def new(cls, *args, **kwargs):
        if isinstance(args[0], cls):
            return args[0]
        else:
            return cls(*args, **kwargs)

obj = C.new()
obj2 = C.new(obj)

【讨论】:

    【解决方案2】:

    执行此操作的标准方法是根本不在__init__ 中进行初始化。在__new__ 中进行操作。

    【讨论】:

      【解决方案3】:

      你可以使用元类

      class InstanceReturnMeta(type):  # You should probably think of a better name
          def __call__(cls, *args, **kwargs):
              if args and isinstance(args[0], cls):
                  return args[0]
              instance = cls.__new__(cls, *args, **kwargs)
              instance.__init__(*args, **kwargs)
              return instance
      
      
      class Test(object):
          __metaclass__ = InstanceReturnMeta
          def __init__(self, value):
              self.value = value
      

      让我们测试一下

      In [3]: instance1 = Test(0)
      In [4]: instance2 = Test(instance1)
      In [5]: print id(instance1) == id(instance2)
      Out[5]: True
      

      id 相同,因此两个变量引用同一个实例。

      附:我假设您使用的是 Python 2,因为您的类显式继承自 object

      【讨论】:

        猜你喜欢
        • 2014-02-02
        • 2015-11-12
        • 1970-01-01
        • 1970-01-01
        • 2021-07-28
        • 2017-02-16
        • 1970-01-01
        • 1970-01-01
        • 2016-02-09
        相关资源
        最近更新 更多