无论“ self”的类别如何,如何在__init__中获取当前的Python类名称? [英] How to get the current Python class name in __init__ regardless of the class of "self"?

查看:106
本文介绍了无论“ self”的类别如何,如何在__init__中获取当前的Python类名称?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

 从线程导入线程
导入日志

def myClassName(myclass):
myclass._class_name = myclass .__ name__
return myclass

@myClassName
class SomeClass(object):
def __init __(self):
class_name = type(self)._ class_name
print我的班级名称 __init__中的是,class_name
self.thread =线程(name = class_name)
self.logger = logging.getLogger(class_name)

更新:



要澄清:




  • 我想要定义的类的名称,而不是传入的
    对象的类。

  • 我不想对名称进行硬编码

  • 我想使一个示例从一个脚本复制/粘贴到另一个脚本

    更加容易,并且更少提及唯一的类名, 更好。
    (继承不是真正有效的方法,因为有足够的自定义
    差异使它笨拙。但是不小心将错误名称
    留给了错误的类是很难找到的。) / li>

解决方案

在Python 3中,这很简单,我们可以使用 __ class __ 在Python 2中,我们可以通过使用元类将类的名称注入函数全局范围中,然后进行清理来实现类似的效果。 / p>

  from functools import包裹
来自类型import FunctionType


def decorate( func,class_name):
@wraps(func)
def wrapper(* args,** kwargs):
sentinel = object()
actual_value = func .__ globals __。get( '__class__',前哨)
func .__ globals __ ['__ class__'] = cl ass_name
尝试:
结果= func(* args,** kwargs)
最终:
(如果实际值已发送):
del func .__ globals __ ['__ class__']
else:
func .__ globals __ ['__ class__'] =实际值
返回结果
返回包装器


class Meta(type):
def __new __(cls,name,bases,attrs):
for k,v in attrs.items():
if isinstance(v,FunctionType):
attrs [k ] = decorate(v,name)
返回类型。__new __(cls,name,bases,atts)


A类:
__metaclass__ =元
def func(self):
print(__ class__)
print('Inside A')


Class B(A):
def func (自身):
打印(__class__)
打印('Inside B')
超级(B,self).func()


B ().func()

输出:

  B 
内部B
A
内部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
尝试:
结果= func(* args,** kwargs)
最终:
(如果实际值被标记):
del func .__ globals __ [' __class__']
其他:
func .__ globals __ ['__ class__'] =实际值
返回结果
返回包装


类Meta(类型):
def __new __(cls,名称,基数,属性):
cls =类型.__ new __(cls,名称,基数,属性)
对于k,v在attrs.items( ):
如果isinstance(v,FunctionType):
setattr(cls,k,decorate(v,cls))
return cls

现在的输出为:

 < class'__main __。B'> B内部的
B
<类________________
在A


I have a number of classes with code like this. Each __init__ starts a thread and a logger with the name of the class. How do I get the name of the current class in its own definition, as a string, inside __init__? Note that self may not be an instance of the current class, so the following is not quite foolproof.

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)

Update:

To clarify:

  • I want the name of the class being defined, not the class of the object passed in.
  • I don't want to hard code the name of the class.
  • I want to make it easy to copy/paste an example from one script to
    another, and the fewer mentions of the unique class name, the better. (Inheritance isn't really efficient, as there are enough custom differences to make it awkward. But accidentally leaving in the name of the wrong class is a hard bug to find.)

解决方案

In Python 3 this is pretty straight forward, we can use the __class__ cell variable to get the current class.

In Python 2 we can achieve something similar by injecting class's name in functions globals scope using a metaclass and later cleaning it up.

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()

Output:

B
Inside B
A
Inside A


To get the __class__ variable as the class object itself we can make few changes:

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

Now output would be:

<class '__main__.B'>
Inside B
<class '__main__.A'>
Inside A

这篇关于无论“ self”的类别如何,如何在__init__中获取当前的Python类名称?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆