buk*_*zor 8 python oop class coerce
我希望这段代码"正常工作":
def main():
c = Castable()
print c/3
print 2-c
print c%7
print c**2
print "%s" % c
print "%i" % c
print "%f" % c
Run Code Online (Sandbox Code Playgroud)
当然,简单的方法是编写int(c)/3,但我想为配置迷你语言启用更简单的perl-ish语法.
值得注意的是,如果我使用"旧式"类(不从对象继承),我可以通过定义一个__coerce__方法来做到这一点,但旧式类已被弃用,将在python3中删除.
当我使用新式类做同样的事情时,我收到此错误:
TypeError: unsupported operand type(s) for /: 'Castable' and 'int'
Run Code Online (Sandbox Code Playgroud)
我相信这是设计的,但是我怎么能用__coerce__新式的类来模拟旧式的行为呢?您可以在下面找到我当前的解决方案,但它非常难看且冗长.
这是相关文件:(我认为)
奖励积分:
print pow(c, 2, 100)
Run Code Online (Sandbox Code Playgroud)
您需要定义__div__是否要c/3工作.Python不会首先将您的对象转换为数字.
这有效,经过几次改进(@jchl的道具)后不那么严重,但似乎应该是不必要的,特别是考虑到你可以免费使用"旧式"课程.
我还在寻找更好的答案.如果没有更好的方法,这在我看来就像Python语言中的回归.
def ops_list():
"calculate the list of overloadable operators"
#<type 'object'> has functions but no operations
not_ops = dir(object)
#calculate the list of operation names
ops = set()
for mytype in (int, float, str):
for op in dir(mytype):
if op.endswith("__") and op not in not_ops:
ops.add(op)
return sorted(ops)
class MetaCastable(type):
__ops = ops_list()
def __new__(mcs, name, bases, dict):
#pass any undefined ops to self.__op__
def add_op(op):
if op in dict:
return
fn = lambda self, *args: self.__op__(op, args)
fn.__name__ = op
dict[op] = fn
for op in mcs.__ops:
add_op( op )
return type.__new__(mcs, name, bases, dict)
class Castable(object):
__metaclass__ = MetaCastable
def __str__(self):
print "str!"
return "<Castable>"
def __int__(self):
print "int!"
return 42
def __float__(self):
print "float!"
return 2.718281828459045
def __op__(self, op, args):
try:
other = args[0]
except IndexError:
other = None
print "%s %s %s" % (self, op, other)
self, other = coerce(self, other)
return getattr(self, op)(*args)
def __coerce__(self, other):
print "coercing like %r!" % other
if other is None: other = 0.0
return (type(other)(self), other)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1084 次 |
| 最近记录: |