Aside from types.new_class
's capability to define the keyword arguments when creating a class. Are there any major differences between the two approaches?
import types
First = type('First',(object,),{'asd':99})
k = First()
Second = types.new_class('Second',(object,),{},lambda x:x)
x = Second()
A metaclass is most commonly used as a class-factory. When you create an object by calling the class, Python creates a new class (when it executes the 'class' statement) by calling the metaclass.
A metaclass in Python is a class of a class that defines how a class behaves. A class is itself an instance of a metaclass. A class in Python defines how the instance of the class will behave. In order to understand metaclasses well, one needs to have prior experience working with Python classes.
First, extract the class body as string. Second, create a class dictionary for the class namespace. Third, execute the class body to fill up the class dictionary. Finally, create a new instance of type using the above type() constructor.
class types. SimpleNamespace. A simple object subclass that provides attribute access to its namespace, as well as a meaningful repr. Unlike object , with SimpleNamespace you can add and remove attributes.
Yes. The answer involves a concept called "metaclasses".
[Metaclasses] are deeper magic than 99% of users should ever worry about. If you wonder whether you need them, you don't (the people who actually need them know with certainty that they need them, and don't need an explanation about why). ⸺ Tim Peters, author of Zen of Python (source)
If you think you're in that 99%, then read no further, feel free to just use type
. It's just as good as types.new_class
except for in the rare situation that you're using metaclasses.
If you want to know more about metaclasses, I suggest you take a look at some of the high quality answers posted to "What are metaclasses in Python?". (I recommend this one.)
Once you understand what a metaclass is, the answer is fairly self-evident. Since type
is a specific metaclass, it will only work if you want to create classes that use it as their metaclass.
However, if you want to use a non-default metaclass
class MySimpleMeta(type):
pass
and a static class won't do
class MyStaticClass(object, metaclass=MySimpleMeta):
pass
then you can use types.new_class
import types
MyStaticClass = types.new_class("MyStaticClass", (object,), {"metaclass": MySimpleMeta}, lambda ns: ns)
# this is equivalent to the above class.
(As a brief aside, the reason that it requires a callable (e.g. lambda ns: ns
) instead of a dictionary is because metaclasses are allowed to care about the order in which the attributes are defined. )
I realise this is late, and hence you've already likely answered this yourself.
Firstly, it seems that you misunderstand the kwds
argument of types.new_class
; it is the class keyword arguments, e.g
class MyMeta(type):
def __new__(metacls, name, bases, attrs, **config):
print(config)
return super().__new__(metacls, name, bases, attrs)
def __init__(cls, name, bases, attrs, **config):
super().__init__(name, bases, attrs)
class SomeCls(metaclass=MyMeta, debug=True):
pass
>> {'debug': True}
is analogous to (without the print)
SomeCls = types.new_class("SomeCls", (), {'debug':True})
These meta-arguments are useful when configuring meta-classes.
I am not really sure as to why new_class
was designed to accept a callable vs a dict directly, but I suspect it was to avoid implicit shared state between "new" classes that did not inherit from one another.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With