是否可以在班級定義的正文中獲取班級名稱?班級體內班級的Python名稱
例如,
class Foo():
x = magic() # x should now be 'Foo'
我知道我可以使用一個類的方法做到這一點靜態外的類主體的:
class Bar():
@classmethod
def magic(cls):
print cls.__name__
Bar.magic()
然而,這不是我想要的,我想在類體內
是否可以在班級定義的正文中獲取班級名稱?班級體內班級的Python名稱
例如,
class Foo():
x = magic() # x should now be 'Foo'
我知道我可以使用一個類的方法做到這一點靜態外的類主體的:
class Bar():
@classmethod
def magic(cls):
print cls.__name__
Bar.magic()
然而,這不是我想要的,我想在類體內
好 - 救一個解決方案 - 這一塊其實沒有那麼複雜!
import traceback
def magic():
return traceback.extract_stack()[-2][2]
class Something(object):
print magic()
它會打印出 「東西」。我不確定提取的堆棧格式是否以任何方式標準化,但它適用於Python 2.6(和2.7和3.1)
AFAIK類的名稱,直到類定義已經被「執行」之類的對象不可用,所以這是不可能的類定義中得到它。
如果您需要類名以備後用,但不要在類定義期間使用它(例如計算其他字段名稱或其他字段名稱),那麼您仍然可以使用類裝飾器自動執行該過程。
def classname (field):
def decorator (klass):
setattr(klass, field, klass.__name__)
return klass
return decorator
(警告:。未測試)
有了這個定義,就可以得到這樣的:
@classname(field='x')
class Foo:
pass
,你會在它那裏得到場x
與類名,如:
print Foo.x
嗯,謝謝你,這不是我想要的,因爲我總是可以用__name__獲得類名,但瞭解類裝飾器可能可以解決我的問題。 – drewrobb
@drewrobb:也許你可以問一個關於設計本身的問題來獲得替代解決方案。 –
class Bar():
@classmethod
def magic(cls):
return cls.__name__
@property
def x(self):
return self.magic()
def y(self):
return self.x
>>> a = Bar()
>>> a.x
'Bar'
>>> a.y()
'Bar'
這樣,您就可以使用x
作爲一個屬性,至少在任何情況下和靜態方法。在類方法中,無論如何,您只需從cls
屬性中獲取類名即可。
這不是我的問題的答案,我想從類定義 – drewrobb
@drewrobb中獲取類名:並且用它做什麼?任何正在執行的代碼都必須從類的方法中調用,在這種情況下,您可以根據方法的類型從「cls .__ name__」或「self .__ class __.__ name__」中獲取類名稱。如果你想做一些非常奇怪的事情,你也可以[爲它創建一個元類](http://docs.python.org/reference/datamodel.html#customizing-class-creation)。 – JAB
Python 2中的元類仍然在執行主體後踢入,因此類的主體不知道類的名稱。 –
我不知道的一種優雅的方式在Python 2.x到做到這一點 - 但它是一種解釋型語言,這意味着什麼大意如下比較簡單會做你想要什麼,如果你」將是安全的重新確定的代碼被執行:
classdef = """\
class %(classname)s(object):
x = '%(classname)s'
print x
"""
exec classdef % {'classname': 'Foo'}
foo = Foo()
print foo
在這裏,你有你的特定情況下,有效的解決方案,但要小心(我寫它主要是爲了證明它確實有可能做這樣的事情):
總之,在這裏你有代碼:
import inspect
def NameAwareClassType():
frameInfo = inspect.getouterframes(inspect.currentframe())[1]
codeContext = frameInfo[4][0]
className = codeContext.split(' ', 1)[1].split('(', 1)[0]
class ClassNameGlobalRemoverType(type):
def __new__(mcs, name, bases, dict):
if name == className:
del globals()['__clsname__']
return type.__new__(mcs, name, bases, dict)
class NameAwareClass(object):
__metaclass__ = ClassNameGlobalRemoverType
globals()['__clsname__'] = className
return NameAwareClass
class A(NameAwareClassType()):
print __clsname__
def __init__(self):
pass
print __clsname__
編輯:https://gist.github.com/1085475 - 有你有一個版本,它允許方法的執行過程中要使用__clsname__
;使沒有太大意義,因爲self.__class__.__name__
是一個更好的辦法和__clsname__
變量已經不抱一個字符串(我很開心這個實驗)
這不可能在Python 2中完成,但Python 3中的元類的__prepare__方法允許您在類的主體開始執行之前將名稱添加到類字典中(您可以從那裏使用它) –
您能描述一下您想如何使用它?這似乎有點無意義,因爲你可以寫Foo .__ name__而不是magic()。在某些情況下,可能會有更好的解決方案。 – viraptor
@Rosh Oxymoron,我認爲這是可能的,它可能不是優雅或高性能或你想要的,但只要你可以在運行時修改AST,你可以做任何你想要的... – GaretJax