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

Qua*_*nic 8 python class

我有许多带有这样代码的类。每个都__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)
Run Code Online (Sandbox Code Playgroud)

更新:

澄清:

  • 我想要定义的类的名称,而不是传入的对象的类。
  • 我不想硬编码类的名称。
  • 我想让将示例从一个脚本复制/粘贴到
    另一个脚本变得容易,并且对唯一类名的提及越少越好。(继承并不是真正有效,因为有足够多的自定义差异使它变得尴尬。但不小心留下错误类的名称是一个很难找到的错误。)

Ash*_*ary 7

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

在 Python 2 中,我们可以通过使用元类在函数全局作用域中注入类的名称并稍后对其进行清理来实现类似的功能。

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()
Run Code Online (Sandbox Code Playgroud)

输出:

B
Inside B
A
Inside A
Run Code Online (Sandbox Code Playgroud)

要将__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
Run Code Online (Sandbox Code Playgroud)

现在输出将是:

<class '__main__.B'>
Inside B
<class '__main__.A'>
Inside A
Run Code Online (Sandbox Code Playgroud)


Rob*_*obᵩ 5

您可以检索一个对象的类的名称,因此:

obj.__class__.__name__
Run Code Online (Sandbox Code Playgroud)

例子:

class SomeClass(object):
    def __init__(self):
        print("I am a %s"%self.__class__.__name__)

class Derived(SomeClass):
    pass

x = SomeClass()
y = Derived()
Run Code Online (Sandbox Code Playgroud)

结果:

$ python x.py
I am a SomeClass
I am a Derived
Run Code Online (Sandbox Code Playgroud)

  • @QuantumMechanic 您需要在实际问题中消除“当前正在执行的类”的歧义,否则人们将以各种不同的方式解释它。 (3认同)