0

I want to be able to call 'person.Person.class' and get back 'class person.Person', like it does for a person object:

>>> p = person.Person()
>>> p.__class__
<class 'person.Person'>
>>> person.Person.__class__
<class 'perframe.datatype.TypeSystemMeta'>

Here is the Person inheritance tree...

class TypeSystem(object):
    __metaclass__ = TypeSystemMeta    

class Model(TypeSystem):
    pass    

class Node(Vertex,Model):
    pass

class Person(Node):
    pass

What's going on here?

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
espeed
  • 4,754
  • 2
  • 39
  • 51

3 Answers3

5

In Python, even classes are objects and every object is an instance of a class. Person refers to the "class object", which is an instance of type. In this case, there's a metaclass in the play - highly confusing metaprogramming magic, but if you want an introduction, see What is a metaclass in Python?. If you declare a class Foo(object), Foo.__class__ is type (things are different and more confusing for old-style classe which don't inherit from object). By the way, this leads to even more weirdness in that type seems to be an instance of itself.

Community
  • 1
  • 1
2

Just use the reference to person.Person:

>>> p = person.Person() 
>>> p.__class__ 
<class 'person.Person'> 
>>> person.Person
<class 'person.Person'> 

A very helpful resource on Python's type system is the original draft of Python's type system for versions 2.2+.

http://www.python.org/download/releases/2.2/descrintro/

jfocht
  • 1,704
  • 1
  • 12
  • 16
1

To understand why you get the result you did, you have to understand what a metaclass is. And to understand that, you have to understand how classes are created in Python.

When you write a class statement, the interpreter opens a new namespace, executes the code in the statement, and looks at the state of the namespace after that code has run. It then works out the important details (the local variables, the name of the class, ...) and passes that to the builtin class type. Instances of type are therefore what we would normally call classes, so type is a "metaclass".

When you override the metaclass, you tell Python not to use type to create your new class. Instead, it will pass the same stuff to a custom class. This allows you to override the defaults in type.

Thus, person.Person was created by passing some arguments to your metaclass. In particular, it is an instance of that class, so its __class__ is the metaclass!

Katriel
  • 120,462
  • 19
  • 136
  • 170