【问题标题】:Determine if __getattr__ is method or attribute call确定 __getattr__ 是方法调用还是属性调用
【发布时间】:2013-12-05 22:10:21
【问题描述】:

有什么方法可以用__getattr__判断方法和属性调用的区别吗?

即在:

class Bar(object):
    def __getattr__(self, name):
        if THIS_IS_A_METHOD_CALL:
            # Handle method call
            def method(**kwargs):
                return 'foo'
            return method
        else:
            # Handle attribute call
            return 'bar'

foo=Bar()
print(foo.test_method()) # foo
print(foo.test_attribute) # bar

这些方法不是本地的,因此无法使用 getattr/callable 来确定它。我也明白方法是属性,可能没有解决方案。只是希望有一个。

【问题讨论】:

  • 你可以判断你应该返回的对象是否是可调用的,但这并不意味着它会被调用......例如:list.reverse 是否足以“如果THIS_IS_A_METHOD_CALL"...或者是方法调用所需的"list.reverse()"

标签: python getattr


【解决方案1】:

不可能知道随后是否从__getattr__ 调用了某个属性,Martijn Pieters 解释说。

虽然不能判断一个属性是否被调用,但是用callable可以知道一个属性是否可以被调用。另一种方法是使用type 来跟踪各种对象,或制作属性名称列表。

class Foo(object):
    bar_attribute = 'callable'

    def __getattr__(self, name):
        instanceOrValue = getattr(self, "bar_%s" %name)

        if callable(instanceOrValue):
            # Handle object that can be called
            def wrap(**kwargs):
                return "is %s" %instanceOrValue(**kwargs)
            return wrap

        # Handle object that can not be called
        return 'not %s' %instanceOrValue

    def bar_method(self, **kwargs):
        return 'callable';
    

foo=Foo()
print(foo.method()) # is callable
print(foo.attribute) # not callable

__getattr__ 只能跟踪某些事情,但在大多数情况下它可能是正确的解决方案,因为更改调用 (__call__) 会对每个调用产生影响。

Difference between calling a method and accessing an attribute

What is a "callable"?

Python __call__ special method practical example

【讨论】:

    【解决方案2】:

    简而言之,不,没有可靠的方法——问题在于方法 Python 中的一个属性——没有区别。它恰好是一个绑定方法的属性。

    你可以检查属性是否是一个方法,但不能保证它会被调用,例如:

    class Test:
        def test(self):
            ...
    
    Test().test  # This accesses the method, but doesn't call it!
    

    没有办法让访问函数的调用知道它在返回时是否会被调用 - 这是一个尚未处理的未来事件。

    如果您愿意假设被访问的方法是被调用的方法,则可以通过如下检查确定它是被访问的方法:

    hasattr(value, "__self__") and value.__self__ is self
    

    value 是您要检查的属性以查看它是方法还是其他属性,self 是您要查看的实例是否是方法。

    如果你需要在它被调用时发生一些事情,你可以利用这个时刻来装饰函数。

    可以在here 找到一个可靠的代码示例。

    【讨论】:

    • 您可以使用callable() 来确定某些东西是否可以调用。但这不是 OP 想要的。他们希望根据结果的用途返回不同的结果for
    • @MartijnPieters Callable 并不意味着它是一种方法。正如我所说,这是不可能的,因为 Python 在请求时不知道该函数是否会被调用,所以我给出了最接近的答案。
    • 您可以使 any 成为可调用的方法。而且它也不一定是方法(描述符绑定),不是真的。
    【解决方案3】:

    你根本无法知道__getattr__ 挂钩中将如何使用对象。例如,您可以在不调用的情况下访问方法,将它们存储在变量中,然后稍后调用它们。

    返回一个带有__call__方法的对象,调用时会被调用:

    class CallableValue(object):
        def __init__(self, name):
            self.name = name
        def __call__(self, *args, **kwargs):
            print "Lo, {} was called!".format(self.name)
    
    class Bar(object):
        def __getattr__(self, name):
            return CallableValue(name)
    

    但它的实例与字符串或列表不同。

    演示:

    >>> class CallableValue(object):
    ...     def __init__(self, name):
    ...         self.name = name
    ...     def __call__(self, *args, **kwargs):
    ...         print "Lo, {} was called!".format(self.name)
    ... 
    >>> class Bar(object):
    ...     def __getattr__(self, name):
    ...         return CallableValue(name)
    ... 
    >>> b = Bar()
    >>> something = b.test_method
    >>> something
    <__main__.CallableValue object at 0x10ac3c290>
    >>> something()
    Lo, test_method was called!
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-16
      • 1970-01-01
      • 2010-09-25
      相关资源
      最近更新 更多