Reputation: 2167
I'm trying to understand how classes work a bit better "under the hood" of python.
If I create a class Foo
like so
class Foo:
bar = True
Foo
is then directly accessible, such as print(Foo)
or print(Foo.bar)
However, if I dynamically create create a class and don't set it to a variable like so
type('Foo',(),{'bar':True})
If done in the interpreter it shows <class '__main__.Foo'>
. However, when I try to print Foo
it's undefined...NameError: name 'Foo' is not defined
Does this mean that when a class is created the "traditional" way (the first Foo class above), that python automatically sets a variable for the class of the same name? Sort of like this
# I realize this is not valid, just to convey the idea
Foo = class Foo:
bar = True
If so, then why doesn't python also create a variable named Foo
set to class Foo when using type()
to create it?
Upvotes: 3
Views: 162
Reputation: 21956
I think you're making this too complicated. If you don't assign a value / object to a symbol, it is always "lost". Doesn't matter if the value / object is a class or something else. Example:
x = 2 + 2
That assigns the value 4
to the symbol x
. Compare to:
2 + 2
The operation is carried out but the result 4
isn't assigned to a symbol.
Exact situation you have with classes.
Upvotes: 0
Reputation: 782
From documentation
class type(name, bases, dict)
With three arguments, return a new type object. This is essentially a dynamic form of the class statement. The name string is the class name and becomes the name attribute; the bases tuple itemizes the base classes and becomes the bases attribute; and the dict dictionary is the namespace containing definitions for class body and becomes the dict attribute. For example, the following two statements create identical type objects:
class X(object):
a = 1
X = type('X', (object,), dict(a=1))
So yes, I think you have the right idea. type()
does create a class but a dynamic form.
Upvotes: 0
Reputation: 36623
Using type
with 3 argument is analogous to using the lambda
to create a function. Without assignment the evaluated expression is garbage collected.
However, just you can still create an instance of the class, just like you can immediately call a lambda function.
>>> lambda x: True
<function <lambda> at 0x0000022FF95AB598>
>>> type('Test', (), {'x': True})
<class '__main__.Test'>
You can also create an instance of the class, just like you can immediately call a function
>>> t = type('Test', (), {'x': True})()
>>> t.x
True
>>> type('Test2', (), {'y': 123})().y
123
>>> (lambda x: True)(1000) # any input returns True
True
Upvotes: 1
Reputation: 1147
let's compare your problem with function statements and lambdas (because they play the same role here), consider this function f
:
def f ():
return 1
the above snippet of code is not an expression at all, it is a python statement that creates a function named f
returning 1
upon calling it.
let's now do the same thing, but in a different way :
f = lambda : 1
the above snippet of code is a python expression (an assignment) that assigns the symbol f
to the lambda expression (which is our function) lambda : 1
. if we didn't do the assignment, the lambda expression would be lost, it is the same as writing >>> 1
in the python REPL and then trying after that to reference it.
Upvotes: 1