在Python中动态地分配对象而不是类 [英] Dynamically assign special methods to objects but not classes in Python

查看:91
本文介绍了在Python中动态地分配对象而不是类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想执行以下操作:

class A(object): pass

a = A()
a.__int__ = lambda self: 3

i = int(a)

不幸的是,这会抛出:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: int() argument must be a string or a number, not 'A'

如果我将特殊方法分配给类A而不是其实例,这只会似乎起作用。有没有追索权?

This only seems to work if I assign the "special" method to the class A instead of an instance of it. Is there any recourse?

我想到的一种方式是:

def __int__(self):
    # No infinite loop
    if type(self).__int__.im_func != self.__int__.im_func:
        return self.__int__()
    raise NotImplementedError()

但是看起来相当丑陋。

谢谢。

推荐答案

Python总是在类上查找特殊的方法,而不是实例(除了旧的,又称遗产,是一种类 - 它们已经被弃用,已经在Python 3中消失了,因为这个古怪的语义主要来自于在实例上查找特殊的方法,所以你真的不要<要使用它们,相信我! - )。

Python always looks up special methods on the class, not the instance (except in the old, aka "legacy", kind of classes -- they're deprecated and have gone away in Python 3, because of the quirky semantics that mostly comes from looking up special methods on the instance, so you really don't want to use them, believe me!-).

为了使一个特殊的类实例可以独立于彼此的特殊方法,你需要给每个实例它自己的类 - 那么你可以在实例(个人) cla上分配特殊的方法ss ,而不影响其他实例,并且过得愉快。如果你想让它看起来像分配给一个属性的实例,而实际分配给一个个性化的每个实例类的属性,你可以得到一个特殊的 __ setattr __ 实现,当然。

To make a special class whose instances can have special methods independent from each other, you need to give each instance its own class -- then you can assign special methods on the instance's (individual) class without affecting other instances, and live happily ever after. If you want to make it look like you're assigning to an attribute the instance, while actually assigning to an attribute of the individualized per-instance class, you can get that with a special __setattr__ implementation, of course.

这是一个简单的例子,明确的分配给类语法:

Here's the simple case, with explicit "assign to class" syntax:

>>> class Individualist(object):
...   def __init__(self):
...     self.__class__ = type('GottaBeMe', (self.__class__, object), {})
... 
>>> a = Individualist()
>>> b = Individualist()
>>> a.__class__.__int__ = lambda self: 23
>>> b.__class__.__int__ = lambda self: 42
>>> int(a)
23
>>> int(b)
42
>>> 

这是一个花哨的版本,你在那里让它看起来像你分配的特殊方法作为一个实例属性(在场景后面,它仍然进入课程):

and here's the fancy version, where you "make it look like" you're assigning the special method as an instance attribute (while behind the scene it still goes to the class of course):

>>> class Sophisticated(Individualist):
...   def __setattr__(self, n, v):
...     if n[:2]=='__' and n[-2:]=='__' and n!='__class__':
...       setattr(self.__class__, n, v)
...     else:
...       object.__setattr__(self, n, v)
... 
>>> c = Sophisticated()
>>> d = Sophisticated()
>>> c.__int__ = lambda self: 54
>>> d.__int__ = lambda self: 88
>>> int(c)
54
>>> int(d)
88

这篇关于在Python中动态地分配对象而不是类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆