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__方法......但我建议不要使用这种黑魔法.
您的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)