Python 获取类名

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14513019/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 11:41:09  来源:igfitidea点击:

Python get class name

python

提问by Low Lifer

So i have this problem, i want to get the name of a python class in this way:

所以我有这个问题,我想以这种方式获取python类的名称:

class TestClass():
    myName = (get class name here automatically)
    saveDirectory = os.path.join(saveDir, myName) # so i can save it in unique location
    def __init__(self):
        pass # do something

However, it seems that __class__.__name__doesn't actually exist as of yet at the time when myNameis created. So i have been forced to put that into the __init__()function, like this:

但是,似乎__class__.__name__myName创建时实际上还不存在。所以我被迫将其放入__init__()函数中,如下所示:

class TestClass():
    def __init__(self):
        self.myName = self.__class__.__name__
        saveDirectory = os.path.join(saveDir, self.myName) # so i can save it in unique location
        pass # do something

But this has a big problem, because I cannot get the name of the class until I instantiate the class, I instend to create a few gigabytes of data for each instance of the class to be saved in the saveDirectory, so it can be re-used later. So I don't actually want to do go ahead with my current solution.

但这有一个大问题,因为在实例化类之前我无法获得类的名称,我打算为类的每个实例创建几GB的数据以保存在saveDirectory中,因此可以重新以后用。所以我实际上不想继续我目前的解决方案。

Is there anyway to get the class name as I have intended? Or am I just dreaming?

有没有办法按照我的意图获得班级名称?还是我只是在做梦?

EDIT:

编辑:

Thanks guys for your great suggestions. I am going to spend a little bit of time taking a look at Metaclasses. Otherwise, I will probably create a dictionary globally, and have references to these instantiated classes instead.

谢谢你们的好建议。我将花一点时间来看看元类。否则,我可能会全局创建一个字典,并引用这些实例化的类。

采纳答案by Andrew Clark

The only way to actually do what you are trying to during the class definition is to use a metaclass:

在类定义期间实际执行您尝试执行的操作的唯一方法是使用元类

def saveDirMeta(name, bases, dct):
    dct['saveDirectory'] = os.path.join(saveDir, name)
    return type(name, bases, dct)

class TestClass(object):
    __metaclass__ = saveDirMeta  # this adds the 'saveDirectory' attribute
    def __init__(self):
        pass # do something

Or on Python 3.x:

或者在 Python 3.x 上:

class TestClass(metaclass=saveDirMeta):
    def __init__(self):
        pass # do something

This is definitely less clear than just using the following:

这绝对不如仅使用以下内容清楚:

class TestClass():
    saveDirectory = os.path.join(saveDir, 'TestClass')
    def __init__(self):
        pass # do something

回答by Eevee

Just use a method?

只用一个方法?

class TestClass(object):
    @classmethod
    def get_save_directory(cls):
        return os.path.join(save_dir, cls.__name__)

Or you could just have a class attribute indicating the save directory; less magic is usually a good thing. Plus you could change the name of the class later without breaking your storage.

或者你可以只拥有一个指示保存目录的类属性;少魔法通常是一件好事。此外,您可以稍后更改类的名称,而不会破坏您的存储空间。

Also, what? Gigabytes?!

还有,什么?千兆?!

回答by Ashwini Chaudhary

I guess what you're doing is not possible, because the class doesn't even exist when you do:

我猜你在做什么是不可能的,因为当你这样做时,这个类甚至不存在:

myName = (get class name here automatically)

myName = (get class name here automatically)

But soon after the class has been interpreted you can pass the class object to some other function to do the job for you.

但是在类被解释后不久,您就可以将类对象传递给其他一些函数来为您完成这项工作。

In [1]: def save_class(cl):
    myName = cl.__name__
    print myName        #or do whatever you wanna do here
   ...:     

In [2]: class A:pass

In [3]: save_class(A)
A

回答by pythonlarry

During class interpretation, there is no "there" there yet. So, yes, what your initial example shows is not possible. But please explain why this would need to be known before the class even technically exists?

在课堂口译期间,那里还没有“那里”。所以,是的,你最初的例子显示的是不可能的。但是请解释为什么需要在类甚至在技术上存在之前就知道这一点?

Barring a good answer to that outstanding question, one is left with trying to get the class' name from:

除非对那个悬而未决的问题有一个很好的回答,否则只能尝试从以下位置获取班级名称:

1. outside the interpreted class definition, uninstantiated

    class demo(object):
        pass

    print demo.__name__ # 'demo'


2. from within the class definition, uninstantiated (or instantiated ;-)

    class demo2(object):
        @classmethod
        def myName(cls):
            return cls.__name__

    print demo2.myName() # 'demo2'
    print demo2().myName() # 'demo2'


or

3. within an actual instance of the class

    class demo3(object):
        def myClassName(self):
            return self.__class__.__name__

    print demo3().myClassName() # 'demo3'

Beyond that, please edit the question and add some details that explain why your initial attempt needs to work the way you want, before instantiation and yet internal to the class definition, while your 2nd example is problematic. Also, how does saveDir get passed/come from? (A global outside of the class?) Please show some code showing how you intend to use what you'd like to work. There may be a way to redesign to get there from here, in effect if not literally.

除此之外,请编辑问题并添加一些详细信息,以解释为什么您的初始尝试需要在实例化之前以您想要的方式工作,但在类定义内部,而您的第二个示例有问题。另外,saveDir 如何通过/来自?(类之外的全局变量?)请展示一些代码,说明您打算如何使用您喜欢的工作。可能有一种重新设计的方法从这里开始,实际上如果不是字面上的。

回答by SingleNegationElimination

Other than the metaclass in F J's answer, I can think of twoother ways. I'll start with the nicer looking one. You don't need to use a metaclass; sometimes a descriptor is perfectly adequate.

除了在FJ的元类的答案,我能想到的2种其他方式。我将从看起来更好看的开始。你不需要使用元类;有时一个描述符就足够了。

class ClassNameDescriptor(object):
    def __get__(self, instance, owner):
        return owner.__name__

class BaseClass(object):
    name = ClassNameDescriptor()

class Foo(BaseClass):
    pass

The other way, if you really needthe class name from insidethe class body (unlikely), you can snoop on the call stack. The class name, as it appears in source, is on the code object being executed by the class definition:

另一种方法,如果你真的需要的类名从内部类体(不太可能),你可以窥探调用堆栈上。出现在源代码中的类名位于类定义正在执行的代码对象上:

import sys

def get_class_name_from_inside_class():
    return sys._getframe().f_back.f_code.co_name

class Foo(object):
    name = get_class_name_from_inside_class()
    print name

Of the ones presented so far, onlythis last one allws you to use the name, as a string, from inside the class body, Unfortunately, this doesn't work in all versions of python, notably IronPython does not implementent the call stack introspection as it's not available in the DLR.

在到目前为止介绍的那些中,只有最后一个允许您在类主体内部使用名称作为字符串,不幸的是,这不适用于所有版本的 python,特别是 IronPython 没有实现调用堆栈自省因为它在 DLR 中不可用。

There's a way to get it without introspecting the stack, portably. It's similar to the answer provided by F J, using a metaclass, but instead uses the __prepare__feature available in Python 3:

有一种方法可以在不内省堆栈的情况下轻松获得它。它类似于 FJ 提供的答案,使用元类,但使用__prepare__Python 3 中可用的功能:

class namedMeta(type):
    def __prepare__(mcls, name, bases, **kwargs):
        return {'name': name}

class Foo(metaclass=named):
    print name

回答by wenjun.yan

try this. you can refer to your current class by _class. (I'm using python 2.7)

尝试这个。您可以通过_class. (我正在使用 python 2.7)

class Meta(type):
    def __init__(self, *args):
        super(Meta, self).__init__(*args)
        self._class = self
        self.saveDir = str(self._class)

class Wow(object):
     __metaclass__ = Meta

>>> Wow.saveDir
>>> Wow().saveDir

回答by Aran-Fey

Since python 3.3, you can use the __qualname__variable:

从 python 3.3 开始,你可以使用__qualname__变量:

class TestClass():
    myName = __qualname__