Python属性可调用

Zah*_*ory 9 python properties callable

有没有办法让一个属性和方法具有相同的名称?我的意思是可以按常规方式使用并可同时调用的属性?像这样:

>>> b = Book()
>>> b.pages
123
>>> b.pages()
123
>>> b.pages(including_toc=False)
123
>>> b.pages(including_toc=True)
127
Run Code Online (Sandbox Code Playgroud)

pha*_*t0m 10

不,你不能.

()总是从左侧的表达式调用一个对象.

这意味着什么,b.pages()可以理解如下:

_tmp = b.pages
_tmp()
Run Code Online (Sandbox Code Playgroud)

如您所见,方法属性.

可以(但不应该)做的是在一些自定义类中包装整数并提供一种__call__方法......但我建议不要使用这种黑魔法.


dbr*_*dbr 5

您的Book类的实例只能调用一个属性pages.该属性可以是任何东西(整数,可调用函数,任何东西),但它只能是件事.

另一种查看事物的方法是在字节码级别 - 给出两行代码:

>>> def a():
...     book.pages
...     book.pages()
... 
Run Code Online (Sandbox Code Playgroud)

这是它的内容disassembles:

>>> dis.dis(a)
  2           0 LOAD_GLOBAL              0 (book)
              3 LOAD_ATTR                1 (pages)
              6 POP_TOP

  3           7 LOAD_GLOBAL              2 (book)
             10 LOAD_ATTR                1 (pages)
             13 CALL_FUNCTION            0
  [...a few more irrelevant lines...]
Run Code Online (Sandbox Code Playgroud)

第一行(book.pages)加载book对象,并从中加载pages属性(LOAD_ATTR)

第二行(book.pages())执行完全相同的操作,加载book对象,加载pages属性,然后调用CALL_FUNCTION属性.

没有理智的方法可以LOAD_ATTR根据最终的使用方式使返回变得不同.你可以得到的最接近的是返回一个像两者一样的奇怪物体

>>> class WeirdInteger(int):
...   def __call__(self, including_toc):
...     print "WeirdInteger(%s) called" % (self)
...
>>> a = WeirdInteger(10)
>>> a
10
>>> a*2
20
>>> a()
WeirdInteger(10) called
Run Code Online (Sandbox Code Playgroud)

但是,不要这样做.没有人使用你的代码会期望该pages属性像这样工作,并且pages将传递给的代码位可能需要一个实际的整数.

而是以Books不同的方式设计您的类(可能会生成pages常规函数,或者为其添加单独的属性pages_without_toc)