【问题标题】:Can functions that are run inside class definitions find a reference to that class?在类定义中运行的函数能否找到对该类的引用?
【发布时间】:2015-12-30 19:49:45
【问题描述】:

我正在编写一个修改类的函数。目前我正在这样做(从我的单元测试中复制):

class ChildClass:
    def __init__(self):
        self.foo = 123

class Subject:
    def __init__(self):
        self.child = ChildClass()

# This is the function I'm talking about. It modifies the class "Subject".
defer_property(Subject, "child", "foo")

assertEqual(123, Subject().foo)

由于函数修改了类,我更喜欢在类定义中运行它,如下所示:

class Subject:
    defer_property("child", "foo")

    def __init__(self):
        self.child = ChildClass()

如果函数可以从上下文中获取对类的引用,那就太好了:

def defer_property(member, property_name):
    cls = get_class_reference_somehow()   # I want this magic function

    prop = property(
        # ...
    )

    setattr(cls, property_name, prop)

这可能吗?

达到类似目的的任何替代方法都很棒。不过我真的不想涉及元类。

【问题讨论】:

    标签: python python-3.5


    【解决方案1】:

    你的函数不必自己设置属性,它可以返回它:

    def defer_property(member, property_name):
        prop = property(
            # ...
        )
        return prop
    
    class Subject:
        foo = defer_property("child", "foo")
    

    【讨论】:

    • 我如何从defer_property 中访问主题实例?
    • @Hubro:技术上Subject是全局的,所以如果你只使用函数修改Subject,你可以参考函数体中的Subject。不过,我不会推荐它。否则,你可能做不到。如果您只需要Subject 为类设置属性,那没关系(您没有说任何关于它的问题),但是,也许这不是一个答案......
    • 其实我很傻。该实例将作为第一个参数传递给 getter 和 setter。
    【解决方案2】:

    在评估主体之前,该类不存在,所以不存在。类声明

    class MyClass(object):
        foo = 3
        def __init__(self):
            pass
    

    大致相当于

    body['foo'] = 3
    def init(self):
        pass
    body['__init__'] = init
    # *Now* create the class object
    MyClass = type('MyClass', (object,), body)
    

    【讨论】:

      【解决方案3】:

      达到类似目标的任何替代方式都很棒。

      装饰者:

      def defer_property(member, property_name):
          def _(cls):
              pass # do stuff here
              return cls
          return _
      

      用法:

      @defer_property("child", "foo")
      class Subject:
          pass
      

      【讨论】:

      • 我没有考虑到这一点,谢谢。这比我现在做的要好得多。
      猜你喜欢
      • 1970-01-01
      • 2018-01-03
      • 1970-01-01
      • 2010-11-16
      • 1970-01-01
      • 1970-01-01
      • 2013-03-18
      • 2014-07-26
      • 2019-09-12
      相关资源
      最近更新 更多