【问题标题】:Using same function as instance and classmethod in python在python中使用与实例和类方法相同的函数
【发布时间】:2011-11-14 11:26:53
【问题描述】:

可以这样做:

class master:
    @combomethod 
    def foo(param):
        param.bar() # Param could be type as well as object

class slaveClass( master ):
    @classmethod 
    def bar(cls):
        print("This is class method")

slaveType = slaveClass
slaveType.foo()

class slaveInstance( master ):
    def __init__(self, data):
        self.data = data
    def bar(self):
        print("This is "+self.data+" method")


slaveType = slaveInstance("instance")
slaveType.foo()

combomethod 在“Creating a method that is simultaneously an instance and class method”中定义。

我的问题是,为什么会这样,默认的第一个参数不能用作组合类的参数?或者至少,为什么我不能将对象作为第一个参数传递给 classmethod?我知道 classmethod 和 instancemethods 之间的区别,我知道装饰器,但我可能不明白内置的 @classmethod 和 self 参数传递是如何进行的。有技术限制吗?或者,为什么combomethod 还没有内置?

【问题讨论】:

  • 请不要在 SO 帖子中使用文字朗读(“smth”)。
  • 我无法理解你在这里问的问题......
  • @Ignacio 我想知道我是否做错了,有没有更简单的方法?我认为可能有一些内置方法可以做同样的事情,如果没有,为什么不呢?

标签: python decorator instance class-method


【解决方案1】:

使用这个:

class A(object):

    @classmethod
    def print(cls):
        print 'A'

    def __print(self):
        print 'B'

    def __init__(self):
        self.print = self.__print


a = A()
a.print()
A.print()

【讨论】:

    【解决方案2】:

    combomethod 在访问时不会创建方法对象,而是创建一个特殊包装的函数。与方法一样,每次访问都会创建一个新对象,在这种情况下是一个新的函数对象。

    class A:
        def __init__(self):
            self.data = 'instance'
    
        @combomethod 
        def foo(param):
            if isinstance(param, A):
                print("This is an " + param.data + " method.")
            elif param is A:
                print("This is a class method.")
    
    >>> a = A()
    >>> A.foo
    <function foo at 0x00CFE810>
    >>> a.foo
    <function foo at 0x00CFE858>
    
    >>> A.foo()
    This is a class method.
    >>> a.foo()
    This is an instance method.
    

    每次访问都是新的:

    >>> A.foo is A.foo
    False
    >>> a.foo is a.foo
    False
    

    foo 真的是_wrapper 伪装的:

    >>> A.foo.__code__.co_name
    '_wrapper'
    

    当从类调用时,闭包有 obj == None(注意这里的 'self' 指的是组合方法,它引用了 self.method 中的原始函数对象):

    >>> print(*zip(A.foo.__code__.co_freevars, A.foo.__closure__), sep='\n')
    ('obj', <cell at 0x011983F0: NoneType object at 0x1E1DF8F4>)
    ('self', <cell at 0x01198530: combomethod object at 0x00D29630>)
    ('objtype', <cell at 0x00D29D10: type object at 0x01196858>)
    

    当作为实例的属性调用时,obj就是实例:

    >>> print(*zip(a.foo.__code__.co_freevars, a.foo.__closure__), sep='\n')
    ('obj', <cell at 0x01198570: A object at 0x00D29FD0>)
    ('self', <cell at 0x01198530: combomethod object at 0x00D29630>)
    ('objtype', <cell at 0x00D29D10: type object at 0x01196858>)
    

    这是存储在组合方法中的原始函数:

    >>> A.foo.__closure__[1].cell_contents.method
    <function foo at 0x00D1CB70>
    >>> A.foo.__closure__[1].cell_contents.method.__code__.co_name
    'foo'
    

    _wrapper 执行self.method,将类或实例作为第一个参数,给定 obj 的值:

    if obj is not None:
        return self.method(obj, *args, **kwargs)
    else:
        return self.method(objtype, *args, **kwargs)
    

    【讨论】:

    • 所以你告诉我组合方法是如何工作的,我理解了大部分。感谢你的付出!您能否也告诉我,为什么它不好,可以以更好的方式完成吗?函数的包装器使其内存效率低下?
    • combomethod 是如何定义的或者可以从哪里导入?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-24
    • 1970-01-01
    • 2020-02-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多