Python 如何重载?

2018-07-21 15:00:44 +08:00
 Cheez

我想要这样的效果:

ans.vote --> 返回数目 ans.vote() --> 赞同答案

可是具体操作时却这样: TypeError: 'NoneType' object is not callable

2867 次点击
所在节点    问与答
25 条回复
hlwjia
2018-07-21 15:21:55 +08:00
你的 ans 是 None ?
mimzy
2018-07-21 15:26:44 +08:00
Python 没有重载(可能不严格,请指正),因为有可变参数和默认参数。

你的 ans 或者实例中的某些东西是 None
Cheez
2018-07-21 15:36:08 +08:00
不是 None,具体见附言.
u2386
2018-07-21 15:39:13 +08:00
Trim21
2018-07-21 15:41:52 +08:00
class vote(int):
def __call__(self, *args, **kwargs):
print('vote')

pass


class a(object):
vote = vote(1)


ans = a()
print(ans.vote)
ans.vote()
u2386
2018-07-21 15:41:52 +08:00
附言里加了 property 的 vote 覆盖了上一个 vote 方法,并且只有 print,没有 return,所以调用这个方法返回是个 None。
Cheez
2018-07-21 17:15:50 +08:00
最后这样好了

```

def intcan(call):
def allcan_func(f):

class vote(int):
def __call__(self, *args, **kwargs):

return call()

def __get__(self, instance, owner):
return vote(f())
return vote()
return allcan_func
```

就是很不优雅(笑哭
@u2386 #6
@Trim21
ipwx
2018-07-21 17:25:53 +08:00
强烈反对楼主的做法。
Cheez
2018-07-21 17:51:19 +08:00
@ipwx 怎么了
yezhiye
2018-07-21 18:25:57 +08:00
这样做挺奇怪的,因为可以定义函数 func def func()...然后 a = func,这样就可以通过 a()执行 func。如果名字一样的话就覆盖了。
Cheez
2018-07-21 19:28:14 +08:00
@yezhiye #10

zhihu.vote()
zhihu.vote

两个一个赞同,一个获取赞同,这不是很爽嘛
Cheez
2018-07-21 19:35:11 +08:00
def intcan(call):
def allcan_func(f):

class allcan_class(int):
def __call__(self, instance, *args, **kwargs):

return call(instance)

def __get__(self, instance, owner):
return allcan_class(f(instance))
return allcan_class()
return allcan_func
最后用这个装饰器实现了 ans.vote,ans.vote()的功能

但是有个问题,调用 ans.vote 的时候会自动调用 ans.vote 值的相关代码,不知道怎么解决
@Trim21 #5
@yezhiye
@ipwx #8
@u2386 #4
Trim21
2018-07-21 19:58:45 +08:00
@Cheez #12 这里没必要重载__get__吧...
Cheez
2018-07-21 20:02:38 +08:00
@Trim21 #13

def vote_call(self):
print('赞同他')

@varCan(vote_call)
def vote(self):
print('获取赞同'+str(self._vote))
return self._vote

get 的时候也是要调用一个函数计算得到值的
Trim21
2018-07-21 20:07:00 +08:00
@Cheez #14 为什么不直接用两个类呢...
这种写法没感觉相比用两个类有什么优势...
方便自定义__call__?
Cheez
2018-07-21 20:12:26 +08:00
@Trim21 #15
调用的时候比较方便一点 TAT
mingyun
2018-07-21 22:43:01 +08:00
函数里定义类 python 有点怪
gnijuohz
2018-07-21 23:19:44 +08:00
不太明白为什么非要都用 vote 这词

从语法上讲名词( property )用 votes 这个复数形式更恰当
然后进行投票用 vote
wangyongbo
2018-07-21 23:49:33 +08:00
这两天升级 django , 从 1.8 升级到 支持 python2.7 的最后一个版本 1.11.
发现
"Using user.is_authenticated() and user.is_anonymous() as a method "
"is deprecated. Remove the parentheses to use it as an attribute.",
之前的使用方法:user.is_authenticated()
现在的使用方法:user.is_authenticated

我看了一下 django 的实现方法

```
class User():

@property
def is_authenticated(self):
return CallableFalse

```
首先用 property 把它变成了一个属性,但是返回的不是一个 bool, 是一个有__call__ 的对象

CallableFalse = CallableBool(False)


```
class CallableBool:
"""
An boolean-like object that is also callable for backwards compatibility.
"""
do_not_call_in_templates = True

def __init__(self, value):
self.value = value

def __bool__(self):
return self.value

def __call__(self):
warnings.warn(
"Using user.is_authenticated() and user.is_anonymous() as a method "
"is deprecated. Remove the parentheses to use it as an attribute.",
RemovedInDjango20Warning, stacklevel=2
)
return self.value

def __nonzero__(self): # Python 2 compatibility
return self.value

def __repr__(self):
return 'CallableBool(%r)' % self.value

def __eq__(self, other):
return self.value == other

def __ne__(self, other):
return self.value != other

def __or__(self, other):
return bool(self.value or other)

def __hash__(self):
return hash(self.value)

```


你觉得这种实现方式 怎么样?

出了 这种需要兼容的代码, 再也没有见过 类似的代码了。
wangyongbo
2018-07-21 23:52:17 +08:00

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/472907

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX