分享

如何在__init__中获取当前的Python类名,而不管“self”的类?

 印度阿三17 2019-08-28

我有很多类,有这样的代码.每个__init__都会启动一个线程和一个带有该类名称的记录器.如何在__init__中以字符串形式获取当前类的名称?请注意,self可能不是当前类的实例,因此以下内容并非万无一失.

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)

更新:

澄清:

>我想要定义类的名称,而不是类的名称
传入的对象.
>我不想硬编码类的名称.
>我希望能够轻松地将示例从一个脚本复制/粘贴到
另一个,并且对独特类名的提及越少越好.
(继承不是很有效,因为有足够的自定义
差异让它变得尴尬.但不小心留下了名字
错误的类是一个难以找到的bug.)

解决方法:

在Python 3中,这非常简单,我们可以使用__class__单元变量来获取当前类.

在Python 2中,我们可以通过使用元类在函数globals范围中注入类的名称并稍后清理它来实现类似的功能.

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__变量作为类对象本身,我们可以进行一些更改:

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

现在输出将是:

<class '__main__.B'>
Inside B
<class '__main__.A'>
Inside A
来源:https://www./content-1-419001.html

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多