我有很多類,有這樣的代碼.每個(gè)__init__都會(huì)啟動(dòng)一個(gè)線程和一個(gè)帶有該類名稱的記錄器.如何在__init__中以字符串形式獲取當(dāng)前類的名稱?請(qǐng)注意,self可能不是當(dāng)前類的實(shí)例,因此以下內(nèi)容并非萬(wàn)無(wú)一失.
from threading import Thread
import logging
def myClassName(myclass):
myclass._class_name = myclass.__name__
return myclass
@myClassName
class SomeClass(object):
def __init__(self):
class_name = type(self)._class_name
print "My class name in __init__ is", class_name
self.thread = Thread(name=class_name)
self.logger = logging.getLogger(class_name)
更新:
澄清:
>我想要定義類的名稱,而不是類的名稱 傳入的對(duì)象. >我不想硬編碼類的名稱. >我希望能夠輕松地將示例從一個(gè)腳本復(fù)制/粘貼到 另一個(gè),并且對(duì)獨(dú)特類名的提及越少越好. (繼承不是很有效,因?yàn)橛凶銐虻淖远x 差異讓它變得尷尬.但不小心留下了名字 錯(cuò)誤的類是一個(gè)難以找到的bug.) 解決方法: 在Python 3中,這非常簡(jiǎn)單,我們可以使用__class__ 單元變量來(lái)獲取當(dāng)前類.
在Python 2中,我們可以通過(guò)使用元類在函數(shù)globals范圍中注入類的名稱并稍后清理它來(lái)實(shí)現(xiàn)類似的功能.
from functools import wraps
from types import FunctionType
def decorate(func, class_name):
@wraps(func)
def wrapper(*args, **kwargs):
sentinel = object()
actual_value = func.__globals__.get('__class__', sentinel)
func.__globals__['__class__'] = class_name
try:
result = func(*args, **kwargs)
finally:
if actual_value is sentinel:
del func.__globals__['__class__']
else:
func.__globals__['__class__'] = actual_value
return result
return wrapper
class Meta(type):
def __new__(cls, name, bases, attrs):
for k, v in attrs.items():
if isinstance(v, FunctionType):
attrs[k] = decorate(v, name)
return type.__new__(cls, name, bases, attrs)
class A:
__metaclass__ = Meta
def func(self):
print(__class__)
print('Inside A')
class B(A):
def func(self):
print(__class__)
print('Inside B')
super(B, self).func()
B().func()
輸出:
B
Inside B
A
Inside A
要將__class__變量作為類對(duì)象本身,我們可以進(jìn)行一些更改:
def decorate(func, cls):
@wraps(func)
def wrapper(*args, **kwargs):
sentinel = object()
actual_value = func.__globals__.get('__class__', sentinel)
func.__globals__['__class__'] = cls
try:
result = func(*args, **kwargs)
finally:
if actual_value is sentinel:
del func.__globals__['__class__']
else:
func.__globals__['__class__'] = actual_value
return result
return wrapper
class Meta(type):
def __new__(cls, name, bases, attrs):
cls = type.__new__(cls, name, bases, attrs)
for k, v in attrs.items():
if isinstance(v, FunctionType):
setattr(cls, k, decorate(v, cls))
return cls
現(xiàn)在輸出將是:
<class '__main__.B'>
Inside B
<class '__main__.A'>
Inside A
來(lái)源:https://www./content-1-419001.html
|