How to get an existing class based on class name? - python

I have a class:
class Test():
pass
I know the class name is "Test". How can I get class Test? A class is an object of class. I would like to get the class object based on its name, the text "Test".
In my project I have many classes defined. I would like to instantiate a class based on its name (without using an if statement).

If the class is defined in the global namespace, you can do it this way:
class Test:
pass
test_class = globals()["Test"]
print(test_class) # -> <class '__main__.Test'>

I don't suggest following such a convention, as this is very bad practice. A class is not an object of class, it's just a class that has been defined. Any objects you define using that class will be an object of that class and have its own instance. Please don't use the same name for different classes, this is almost never maintainable and you should never do it this way.

Related

How to properly access and set class variables in a derived class?

Supposed that you have a python class (say B) that is a derived class of some other class (say A) and that class A has both class variables and #classmethods that help you change or view these class variables. I had assumed that a #classmethod in class A that sets a class A class variable using the syntax cls.variable_name = value would work.
This seems to work sometimes but not always which confuses me. Below is an example that does not set the class variables as I would expect. Therefore I cannot tell what cls.something will be accessing and so I have to use A.something which seems that I will be missing the capabilities of cls.something in #classmethods. What does cls.something actually access in class methods and why does the following example not set the test class class variables?
The following example with output hopefully demonstrates what I mean:
class Test():
epf = 'A'
#classmethod
def set_formats(cls, p):
cls.epf = p
#classmethod
def form(cls):
return cls.epf
class Mytest(Test):
pass
Here is the output:
>>>c=Mytest
>>>Test.form()
'A'
>>>c.set_formats(p='a')
>>>Test.epf
'A'
>>>c.form()
'a'
>>>c.epf
'a'
So in this example the classmethods are not changing the class variable as I would expect and instead an instance variable seems to appear. If I do the above without a derived class then it works as expected. Hmm? Clearly missing something here!
Now if I change the c.set_formats(p='a', f='A') to Test.set_formats(p='a', f='A') it does work. Is it because c.set_formats uses the class method with cls being an instance?
Edit: Made the code much smaller and changed conventions as requested.
Is it because c.set_formats uses the class method with cls being an instance?
Yes, you can check via print calls showing the ids of the involved objects.

Python built-in functions for class object?

I'm new to python. I've heard that everything is an object when it comes to python even if class or function.
As far as I know, the class object is created when the program starts. So I wonder if there's some function for initializing class variables or doing something.
init function can't do because its parameter is self which's for an instance of the class. I want to access the class itself.
class Example():
def __init__(self):
# I know that this function is called when an instance of this class is created
pass
def __something__(cls):
# Is there some function for initializing class object?
# What I wanna do is I want to initialize class variables or call some functions...
# But __init__ function can't do because its parameter is self.
pass
In Python the class object is created at run time as Python is a Dynamic Language.
So if you want to initiate class variables you could just set them right after class definition
class Cls:
cls_var = "before"
print(Cls.cls_var)
Cls.cls_var = "after"
print(Cls.cls_var)
this would print "before" and "after"
you can operate the class you defined directly.
for example, your class name is Example, you can use buildin method dir to see the class method (dir(Example)), use type to see the class type (type(Example)), __dict__ see the class attributes(Example.__dict__) ...

Getting the name of a class which has a meta class

Suppose I define a class A with a meta class like this:
class Meta(type):
pass
class A(metaclass=Meta):
pass
Then, when I try to access the name of class A I get the name of the meta class:
A.__class__.__name__
# 'Meta'
However, shouldn't it give me A, my defined class?
Note: I tried to use A.__mro__[0].__name__ and it does give me A, but I am still confused why A.__class__ gives me the meta class name. Does anyone has an explanation of this?
The __class__ dunder reports:
the class to which a class instance belongs.
Quote from instance.__class__
The class A belongs to the class of it's metaclass - only instances of A belong to the class A itself.
a = A()
print(a.__class__.__name__) # 'A'
print(A.__class__.__name__) # 'Meta'
class P: pass
print(P.__class__.__name__) # type
print(P().__class__.__name__) # P
To get the name of the class itself simply use
A.__name__
if you really need it.
I am still a way to groke all of answer to What are metaclasses in Python? - maybe it helps you out.
A is already the class - its name is under A.__name__.
If you try A.__class__.__name__ you will get to the class of which A is instance (that is, its metaclass), name.
A.__mro__[0].__name__ will follow the "method resolution order" for the class A - the __mro__ object is a tuple with all the class hyerarchy that starts in the defined class itself and ends in object. So, A.__mro__[0] will always be A itself - and A.__mro__[0].__name__ is the same as A.__name__.
The __name__ and __qualname__ attributes are writable attributes: changing { __qualname__ after the class is created will change the default __repr__ for instances of that class, for example. Although they are in the language definition and "live" in slots in the class (not on it's dictionary), it is possible to create a __name__ property (I mean, the built-in property object, or any other descriptor) on the metaclass that will dynamically change the __name__ attribute of a class (but not __qualname__ - this must be an attribute of the class, and must be a string)

Use abstract base class to force implementation of class property?

I would like to use an abstract base class to force implementation of a class attribute in a concrete class. I know how to force implementation of a generic attribute using #abc.abstractproperty. There are lots of SO answers about how to do that - I've read about 10 of them :) But I would like to ensure that the concrete class must define the abstract attribute as a class attribute and NOT as an instance attribute. Anyone know how to do this?
EDITED to address question:
I have users who will define concrete classes from the ABC. Certain abstract properties need to be "concretized" as class attributes. The checking needs to happen the first time they instantiate the concrete class - not sooner. Ideally, if they mistakenly define an abstract property as an instance attribute, a TypeError will be raised that flags their mistake.
The point is that the value of the class attribute should be the same for all instances of the concrete class.
I think I am missing some knowledge about Python internals that would help me address this question properly...
import abc
class MyABC(object):
__metaclass__ = abc.ABCMeta
#abc.abstractproperty
def foo():
return 'we never run this line'
# I want to enforce this kind of subclassing
class GoodConcrete(MyABC):
#classmethod
def foo(cls):
return 1 # value is the same for all class instances
# I want to forbid this kind of subclassing
class BadConcrete(MyABC):
def foo(self, val):
self.foo = val

Refer to object in parent class from nested class in Python

In Python (2.7) one can use nested class declarations which is sometimes handy to organise local classes.
However, I can't figure out how to reference a class in a parent class so I can derive from it.
A minimal example is this:
class A(object):
class B(object):
pass
class C(object):
class D(A.B): # <-- fails with "NameError: name 'A' is not defined"
pass
How can I make class D derive from class B given the nested structure of the class declaration?
You can't. You can't reference it as A.B, because A is not yet defined (you are in the middle of the definition), and you can't reference it as B because as per PEP 227, names in class scope are not accessible:
Names in class scope are not accessible. Names are resolved in
the innermost enclosing function scope. If a class definition
occurs in a chain of nested scopes, the resolution process skips
class definitions. This rule prevents odd interactions between
class attributes and local variable access. If a name binding
operation occurs in a class definition, it creates an attribute on
the resulting class object. To access this variable in a method,
or in a function nested within a method, an attribute reference
must be used, either via self or via the class name.
An alternative would have been to allow name binding in class
scope to behave exactly like name binding in function scope. This
rule would allow class attributes to be referenced either via
attribute reference or simple name. This option was ruled out
because it would have been inconsistent with all other forms of
class and instance attribute access, which always use attribute
references. Code that used simple names would have been obscure.
That said, even if it was possible, this kind of definition looks really obscure and probably can be refactored into something simpler.
Edit: if you really, really want your class hierarchy look like this, you can just "monkey patch" A:
class A(object):
class B(object):
pass
class _C(object):
class D(A.B):
pass
A.C = _C

Categories