Mar*_*nen 10 python methods class-method python-3.x
我想做这样的事情:
class X:
@classmethod
def id(cls):
return cls.__name__
def id(self):
return self.__class__.__name__
Run Code Online (Sandbox Code Playgroud)
现在要求id()它的类或它的实例:
>>> X.id()
'X'
>>> X().id()
'X'
Run Code Online (Sandbox Code Playgroud)
显然这个确切的代码不起作用,但有没有类似的方法使它工作?或者任何其他解决方法来获得这样的行为没有太多"hacky"的东西?
Ash*_*ary 19
不知道你的实际用例是什么,但你可以使用描述符做这样的事情:
class Desc(object):
def __get__(self, ins, typ):
if ins is None:
print 'Called by a class.'
return lambda : typ.__name__
else:
print 'Called by an instance.'
return lambda : ins.__class__.__name__
class X(object):
id = Desc()
x = X()
print x.id()
print X.id()
Run Code Online (Sandbox Code Playgroud)
输出:
Called by an instance.
X
Called by a class.
X
Run Code Online (Sandbox Code Playgroud)
Mar*_*ers 13
类和实例方法存在于同一名称空间中,您不能重用这样的名称; id在这种情况下,最后的定义是胜利.
类方法将继续在实例上工作,但是,不需要创建单独的实例方法; 只需使用:
class X:
@classmethod
def id(cls):
return cls.__name__
Run Code Online (Sandbox Code Playgroud)
因为该方法继续绑定到类:
>>> class X:
... @classmethod
... def id(cls):
... return cls.__name__
...
>>> X.id()
'X'
>>> X().id()
'X'
Run Code Online (Sandbox Code Playgroud)
这是明确记录的:
它可以在类(例如
C.f())或实例(例如C().f())上调用.除了类之外,该实例被忽略.
通过将方法的实例绑定版本显式绑定到实例(而不是类),可以非常简洁地完成它.Python将调用在调用时找到的实例属性(因为它在类之前搜索实例),并且在调用when时找到类绑定方法.Class().__dict__Class().foo()__dict__Class.__dict__Class.foo()
这有许多潜在的用例,但是它们是否反模式是有争议的:
class Test:
def __init__(self):
self.check = self.__check
@staticmethod
def check():
print('Called as class')
def __check(self):
print('Called as instance, probably')
Run Code Online (Sandbox Code Playgroud)
>>> Test.check()
Called as class
>>> Test().check()
Called as instance, probably
Run Code Online (Sandbox Code Playgroud)
或者......让我们说我们希望能够滥用以下内容map():
class Str(str):
def __init__(self, *args):
self.split = self.__split
@staticmethod
def split(sep=None, maxsplit=-1):
return lambda string: string.split(sep, maxsplit)
def __split(self, sep=None, maxsplit=-1):
return super().split(sep, maxsplit)
Run Code Online (Sandbox Code Playgroud)
>>> s = Str('w-o-w')
>>> s.split('-')
['w', 'o', 'w']
>>> Str.split('-')(s)
['w', 'o', 'w']
>>> list(map(Str.split('-'), [s]*3))
[['w', 'o', 'w'], ['w', 'o', 'w'], ['w', 'o', 'w']]
Run Code Online (Sandbox Code Playgroud)
小智 5
自 Python 3.4 以来,“类型”提供了一些非常有趣的东西:DynamicClassAttribute
它并没有 100% 完成您的想法,但它似乎密切相关,您可能需要稍微调整一下我的元类,但是,粗略地说,您可以拥有它;
from types import DynamicClassAttribute
class XMeta(type):
def __getattr__(self, value):
if value == 'id':
return XMeta.id # You may want to change a bit that line.
@property
def id(self):
return "Class {}".format(self.__name__)
Run Code Online (Sandbox Code Playgroud)
这将定义您的类属性。对于实例属性:
class X(metaclass=XMeta):
@DynamicClassAttribute
def id(self):
return "Instance {}".format(self.__class__.__name__)
Run Code Online (Sandbox Code Playgroud)
这可能有点矫枉过正,尤其是如果您想远离元类。这是我想在我身边探索的一个技巧,所以我只想分享这颗隐藏的宝石,以防你可以擦亮它并让它发光!
>>> X().id
'Instance X'
>>> X.id
'Class X'
Run Code Online (Sandbox Code Playgroud)
瞧...