链接:https://www.zhihu.com/question/19754936/answer/43271191
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
-
low-level constructors named __new__() – 低级别的构造函数.
Note: Python 的 class __init__ 并不是其他语言意义上的构造函数,
在 new 创建实例后对实例属性初始化的函数. -
descriptors, a generalized way to customize attribute access – 描述符.
或者说描述符协议支持.descriptor protocol __get__, __set__ ,__delete__ 等,
可以阅读 descriptor 文档 -
static methods and class methods - 静态方法和类方法
-
properties (computed attributes) – 属性访问 setter getter.
-
decorators (introduced in Python 2.4) – 装饰器.
现在装饰器语法糖遍布各Python框架. -
slots – 用户设置后可以限定实例的属性.
在 Python2 中替代 __dict__, 可以节省近 2/3 内存, Python3 中可以
不因为优化内存使用率而使用 slots, 因为 __dict__ 结构内存做了优化,
Note: __dict__ 并不是 Python 意义上的内置的 dict, 其实是一个 proxy 类. -
a new Method Resolution Order (MRO) – MRO 方法解析次序改变
(由左递归改为C3算法)
Python 新式类介绍 (包含 new-style-and-classic-classes 文档翻译)
http://python-history.blogspot.com/2010/06/inside-story-on-new-style-classes.html
链接:https://www.zhihu.com/question/19754936/answer/28288505
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
在本机进行了测试,环境为 py 2.7.3
class Foo(object):
pass
class Foo1:
pass
print type(Foo), type(Foo1)
print dir(Foo)
print dir(Foo1)
print isinstance(Foo, object)
print isinstance(Foo1, object)
结果如下:
<type 'type'> <type 'classobj'>
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
['__doc__', '__module__']
True
True(这个 True 有些疑问,Foo1 不应是 object 的实例啊)
还有一个问题是上面兄弟说 py 3.0 以上 object 已经作为默认基类被继承了(跟 java 一样),本机环境不太方便测试,所以不知是否正确.
python2:
>>> class Foo: pass
...
>>> type(Foo())
<type 'instance'>
>>> class Bar(object): pass
...
>>> type(Bar())
<class '__main__.Bar'>
可以看出区别类型上有区别,这两种类型的区别在此处文档说明:
https://docs.python.org/release/2.5.2/ref/node33.html
https://www.python.org/download/releases/2.2.3/descrintro/
python3:
python3已经把旧类型去掉了,也就是说已经隐式继承了object,所以,python3中写不写继承object都是没有区别的
Python Types and Objects
Copyright © 2005-2009 Shalabh Chaturvedi
About This Book
Explains Python new-style objects:
-
what are
<type 'type'>
and<type 'object'>
-
how user defined classes and instances are related to each other and to built-in types
-
what are metaclasses
New-style implies Python version 2.2 and upto and including 3.x. There have been some behavioral changes during these version but all the concepts covered here are valid. The system described is sometimes called the Python type system, or the object model.
This book is part of a series:
-
Python Types and Objects [you are here]
This revision:
Discuss | Latest version | Cover page
Author: shalabh@cafepy.com
Table of Contents
List of Figures
-
1.1.
A Clean Slate
2.1.
Chicken and Egg
2.2.
Some Built-in Types
2.3.
User Built Objects
3.1.
The Python Objects Map
4.1.
Relationships
4.2.
Transitivity of Relationships
List of Examples
-
1.1.
Examining an integer object
2.1.
Examining
<type 'object'>
and <type 'type'>
2.2.
There's more to <type 'object'>
and <type 'type'>
2.3.
Examining some built-in types
2.4.
Creating new objects by subclassing
2.5.
Creating new objects by instantiating
2.6.
Specifying a type object while using class
statement
3.1.
More built-in types
3.2.
Examining classic classes
Some points you should note:
-
This book covers the new-style objects (introduced a long time ago in Python 2.2). Examples are valid for Python 2.5 and all the way to Python 3.x.
-
This book is not for absolute beginners. It is for people who already know Python (even a little Python) and want to know more.
-
This book provides a background essential for grasping new-style attribute access and other mechanisms (descriptors, properties and the like). If you are interested in only attribute access, you could go straight toPython Attributes and Methods, after verifying that you understand the Summary of this book.
Happy pythoneering!
So what exactly is a Python object? An object is an axiom in our system - it is the notion of some entity. We still define an object by saying it has:
-
Identity (i.e. given two names we can say for sure if they refer to one and the same object, or not).
-
A value - which may include a bunch of attributes (i.e. we can reach other objects through
objectname.attributename
). -
A type - every object has exactly one type. For instance, the object
2
has a typeint
and the object"joe"
has a typestring
. -
One or more bases. Not all objects have bases but some special ones do. A base is similar to a super-class or base-class in object-oriented lingo.
If you are more of the 'I like to know how the bits are laid out' type as opposed to the 'I like the meta abstract ideas' type, it might be useful for you to know that each object also has a specific location in main memory that you can find by calling the id()
function.
The type and bases (if they exist) are important because they define special relationships an object has with other objects. Keep in mind that the types and bases of objects just other objects. This will be re-visited soon.
You might think an object has a name but the name is not really part of the object. The name exists outside of the object in a namespace (e.g. a function local variable) or as an attribute of another object.
Even a simple object such as the number 2
has a lot more to it than meets the eye.
Example 1.1. Examining an integer object
>>> two = 2 >>> type(two) <type 'int'> >>> type(type(two)) <type 'type'> >>> type(two).__bases__ (<type 'object'>,) >>> dir(two) ['__abs__', '__add__', '__and__', '__class__', '__cmp__', '__coerce__', '__delattr__', '__div__', '__divmod__', '__doc__', '__float__', '__floordiv__', '__format__', '__getattribute__', '__getnewargs__', '__hash__', '__hex__', '__index__', '__init__', '__int__', '__invert__', '__long__', '__lshift__', '__mod__', '__mul__', '__neg__', '__new__', '__nonzero__', '__oct__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdiv__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__xor__', 'conjugate', 'denominator', 'imag', 'numerator', 'real']
Here we give an integer the name | |
The type of this object is | |
Hmm.. the type of | |
Also, the | |
Let's list all the attributes present on this original integer object - wow that's a lot. |
You might say "What does all this mean?" and I might say "Patience! First, let's go over the first rule."
The built-in int
is an object. This doesn't mean that just the numbers such as 2
and 77
are objects (which they are) but also that there is another object called int
that is sitting in memory right beside the actual integers. In fact all integer objects are pointing to int
using their __class__
attribute saying "that guy really knows me". Calling type()
on an object just returns the value of the __class__
attribute.
Any classes that we define are objects, and of course, instances of those classes are objects as well. Even the functions and methods we define are objects. Yet, as we will see, all objects are not equal.
We now build the Python object system from scratch. Let us begin at the beginning - with a clean slate.
You might be wondering why a clean slate has two grey lines running vertically through it. All will be revealed when you are ready. For now this will help distinguish a slate from another figure. On this clean slate, we will gradually put different objects, and draw various relationships, till it is left looking quite full.
At this point, it helps if any preconceived object oriented notions of classes and objects are set aside, and everything is perceived in terms of objects (our objects) and relationships.
As we introduce many different objects, we use two kinds of relationships to connect. These are the subclass-superclass relationship (a.k.a. specialization or inheritance, "man is an animal", etc.) and the type-instancerelationship (a.k.a instantiation, "Joe is a man", etc.). If you are familiar with these concepts, all is well and you can proceed, otherwise you might want to take a detour through the section called “Object-Oriented Relationships”.
We examine two objects: <type 'object'>
and <type 'type'>
.
The names of the two primitive objects within Python. Earlier | |
Exploring | |
Exploring |
Let's make use of our slate and draw what we've seen.
These two objects are primitive objects in Python. We might as well have introduced them one at a time but that would lead to the chicken and egg problem - which to introduce first? These two objects are interdependent - they cannot stand on their own since they are defined in terms of each other.
Continuing our Python experimentation:
Whoa! What happened here? This is just Dashed Arrow Up Rule in action. Since | |
Applying both Dashed Arrow Up Rule and Dashed Arrow Down Rule, we can effectively reverse the direction of the dashed arrow. Yes, it is still consistent. |
If the above example proves too confusing, ignore it - it is not much use anyway.
Now for a new concept - type objects. Both the objects we introduced are type objects. So what do we mean by type objects? Type objects share the following traits:
-
They are used to represent abstract data types in programs. For instance, one (user defined) object called
User
might represent all users in a system, another once calledint
might represent all integers. -
They can be subclassed. This means you can create a new object that is somewhat similar to exsiting type objects. The existing type objects become bases for the new one.
-
They can be instantiated. This means you can create a new object that is an instance of the existing type object. The existing type object becomes the
__class__
for the new object. -
The type of any type object is
<type 'type'>
. -
They are lovingly called types by some and classes by others.
Yes you read that right. Types and classes are really the same in Python (disclaimer: this doesn't apply to old-style classes or pre-2.2 versions of Python. Back then types and classes had their differences but that was a long time ago and they have since reconciled their differences so let bygones be bygones, shall we?). No wonder the type()
function and the __class__
attribute get you the same thing.
The term class was traditionally used to refer to a class created by the class
statement. Built-in types (such as int
and string
) are not usually referred to as classes, but that's more of a convention thing and in reality types and classes are exactly the same thing. In fact, I think this is important enough to put in a rule:
Class is Type is Class
The term type is equivalent to the term class in all version of Python >= 2.3.
Types and (er.. for lack of a better word) non-types (ugh!) are both objects but only types can have subcasses. Non-types are concrete values so it does not make sense for another object be a subclass. Two good examples of objects that are not types are the integer 2
and the string "hello"
. Hmm.. what does it mean to be a subclass of 2
?
Still confused about what is a type and what is not? Here's a handy rule for you:
Type Or Non-type Test Rule
If an object is an instance of <type 'type'>
, then it is a type. Otherwise, it is not a type.
Looking back, you can verify that this is true for all objects we have come across, including <type 'type'>
which is an instance of itself.
To summarize:
-
<type 'object'>
is an instance of<type 'type'>
. -
<type 'object'>
is a subclass of no object. -
<type 'type'>
is an instance of itself. -
<type 'type'>
is a subclass of<type 'object'>
. -
There are only two kinds of objects in Python: to be unambiguous let's call these types and non-types. Non-types could be called instances, but that term could also refer to a type, since a type is always an instance of another type. Types could also be called classes, and I do call them classes from time to time.
Note that we are drawing arrows on our slate for only the direct relationships, not the implied ones (i.e. only if one object is another's __class__
, or in the other's __bases__
). This make economic use of the slate and our mental capacity.
A few built-in types are shown above, and examined below.
The built-in | |
Its type is | |
It has one base (a.k.a. superclass), | |
Ditto for | |
This is how you create an instance of | |
The type of a list is |
When we create a tuple or a dictionary, they are instances of the respective types.
So how can we create an instance of mylist
? We cannot. This is because mylist
is a not a type.
The built-in objects are, well, built into Python. They're there when we start Python, usually there when we finish. So how can we create new objects?
New objects cannot pop out of thin air. They have to be built using existing objects.
The | |
Don't do this in Python 2.x or you will end up with an object that is an old-style class, everything you read here will be useless and all will be lost. | |
Multiple bases are fine too. | |
Most built-in types can be subclassed (but not all). |
After the above example, C.__bases__
contains <type 'object'>
, and MyList.__bases__
contains <type 'list'>
.
Subclassing is only half the story.
The call operator ( | |
Python syntax creates new objects for some built-in types. The square brackets create an instance of |
After the above exercise, our slate looks quite full.
Note that by just subclassing <type 'object'>
, the type C
automatically is an instance of <type 'type'>
. This can be verified by checking C.__class__
. Why this happens is explained in the next section.
Some questions are probably popping up in your head at this point. Or maybe they aren't, but I'll answer them anyway:
Q: | How does Python really create a new object? |
A: | Internally, when Python creates a new object, it always uses a type and creates an instance of that object. Specifically it uses the |
Q: | When using instantiation, I specify the type, but how does Python know which type to use when I use subclassing? |
A: | It looks at the base class that you specified, and uses its type as the type for the new object. In the example Example 2.4, “Creating new objects by subclassing” , A little thought reveals that under most circumstances, any subclasses of |
Advanced Material Ahead
Advanced discussion ahead, tread with caution, or jump straight to the next section.
We really ended up with a map of different kinds of Python objects in the last chapter.
Here we also unravel the mystery of the vertical grey lines. They just segregate objects into three spaces based on what the common man calls them - metaclasses, classes, or instances.
Various pedantic observations of the diagram above:
-
Dashed lines cross spacial boundaries (i.e. go from object to meta-object). Only exception is
<type 'type'>
(which is good, otherwise we would need another space to the left of it, and another, and another...). -
Solid lines do not cross space boundaries. Again,
<type 'type'>
-><type 'object'>
is an exception. -
Solid lines are not allowed in the rightmost space. These objects are too concrete to be subclassed.
-
Dashed line arrow heads are not allowed rightmost space. These objects are too concrete to be instantiated.
-
Left two spaces contain types. Rightmost space contains non-types.
-
If we created a new object by subclassing
<type 'type'>
it would be in the leftmost space, and would also be both a subclass and instance of<type 'type'>
.
Also note that <type 'type'>
is indeed a type of all types, and <type 'object'>
a superclass of all types (except itself).
-
There are two kinds of objects in Python:
-
Type objects - can create instances, can be subclassed.
-
Non-type objects - cannot create instances, cannot be subclassed.
-
-
<type 'type'>
and<type 'object'>
are two primitive objects of the system. -
objectname.__class__
exists for every object and points the type of the object. -
objectname.__bases__
exists for every type object and points the superclasses of the object. It is empty only for<type 'object'>
. -
To create a new object using subclassing, we use the
class
statement and specify the bases (and, optionally, the type) of the new object. This always creates a type object. -
To create a new object using instantiation, we use the call operator (
()
) on the type object we want to use. This may create a type or a non-type object, depending on which type object was used. -
Some non-type objects can be created using special Python syntax. For example,
[1, 2, 3]
creates an instance of<type 'list'>
. -
Internally, Python always uses a type object to create a new object. The new object created is an instance of the type object used. Python determines the type object from a
class
statement by looking at the bases specified, and finding their types. -
issubclass(A,B)
(testing for superclass-subclass relationship) returnsTrue
iff:-
B
is inA.__bases__
, or -
issubclass(Z,B)
is true for anyZ
inA.__bases__
.
-
-
isinstance(A,B)
(testing for type-instance relationship) returnsTrue
iff:-
B
isA.__class__
, or -
issubclass(A.__class__,B)
is true.
-
-
Squasher is really a python. (Okay, that wasn't mentioned before, but now you know.)
The following example shows how to discover and experiment with built-in types.
Example 3.1. More built-in types
>>> import types >>> types.ListType is list True >>> def f(): ... pass ... >>> f.__class__ is types.FunctionType True >>> >>> class MyList(list): ... pass ... >>> class MyFunction(types.FunctionType): ... pass ... Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: type 'function' is not an acceptable base type >>> dir(types) ['BooleanType', 'DictProxyType', 'DictType', ..]
So we can create new objects with any relationship we choose, but what does it buy us?
The relationships between objects determine how attribute access on the object works. For example, when we say objectname.attributename
, which object do we end up with? It all depends on objectname
, its type, and its bases (if they exist).
Attribute access mechanisms in Python are explained in the second book of this series: Python Attributes and Methods.
This is a note about classic classes in Python. We can create classes of the old (pre 2.2) kind by using a plain class statement.
A class statement specifying no bases creates a classic class Remember that to create a new-style class you must specify | |
Its type is an object we haven't seen before (in this book). | |
The type of classic classes is an object called | |
It looks and smells like just another type object. |
The types.ClassType
object is in some ways an alternative <type 'type'>
. Instances of this object (classic classes) are types themselves. The rules of attribute access are different for classic classes and new-style classes. The types.ClassType
object exists for backward compatibility and may not exist in future versions of Python. Other sections of this book should not be applied to classic classes.
Comment on this book here: discussion page. I appreciate feedback!
That's all, folks!
Can Skim Section
This oddly placed section explains the type-instance and supertype-subtype relationships, and can be safely skipped if the reader is already familiar with these OO concepts. Skimming over the rules below might be useful though.
While we introduce many different objects, we only use two kinds of relationships (Figure 4.1, “Relationships”):
-
is a kind of (solid line): Known to the OO folks as specialization, this relationship exists between two objects when one (the subclass) is a specialized version of the other (the superclass). A snake is a kind of reptile. It has all the traits of a reptile and some specific traits which identify a snake.
Terms used: subclass of, superclass of and superclass-subclass.
-
is an instance of (dashed line): Also known as instantiation, this relationship exists between two objects when one (the instance) is a concrete example of what the other specifies (the type). I have a pet snake named Squasher. Squasher is an instance of a snake.
Terms used: instance of, type of, type-instance and class-instance.
Note that in plain English, the term 'is a' is used for both of the above relationships. Squasher is a snake and snake is a reptile are both correct. We, however, use specific terms from above to avoid any confusion.
We use the solid line for the first relationship because these objects are closer to each other than ones related by the second. To illustrate - if one is asked to list words similar to 'snake', one is likely to come up with 'reptile'. However, when asked to list words similar to 'Squasher', one is unlikely to say 'snake'.
It is useful at this point to note the following (independent) properties of relationships:
Dashed Arrow Up Rule
If X is an instance of A, and A is a subclass of B, then X is an instance of B as well.
Dashed Arrow Down Rule
If B is an instance of M, and A is a subclass of B, then A is an instance of M as well.
In other words, the head end of a dashed arrow can move up a solid arrow, and the tail end can move down (shown as 2a and 2b in Figure 4.2, “Transitivity of Relationships” respectively). These properties can be directly derived from the definition of the superclass-subclass relationship.
Applying Dashed Arrow Up Rule, we can derive the second statement from the first:
-
Squasher is an instance of snake (or, the type of Squasher is snake).
-
Squasher is an instance of reptile (or, the type of Squasher is reptile).
Earlier we said that an object has exactly one type. So how does Squasher have two? Note that although both statements are correct, one is more correct (and in fact subsumes the other). In other words:
-
Squasher.__class__
issnake
. (In Python, the__class__
attribute points to the type of an object). -
Both
isinstance(Squasher, snake)
andisinstance(Squasher, reptile)
are true.
A similar rules exists for the superclass-subclass relationship.
Combine Solid Arrows Rule
If A is a subclass of B, and B is a subclass of C, then A is a subclass of C as well.
A snake is a kind of reptile, and a reptile is a kind of animal. Therefore a snake is a kind of animal. Or, in Pythonese:
-
snake.__bases__
is(reptile,)
. (The__bases__
attribute points to a tuple containing superclasses of an object). -
Both
issubclass(snake, reptile)
andissubclass(snake, animal)
are true.
Note that it is possible for an object to have more than one base.
[descrintro] Unifying types and classes in Python 2.2.
[pep-253] Subclassing Built-in Types.
Colophon
This book was written in DocBook XML. The HTML version was produced using DocBook XSL stylesheets andxsltproc
. The PDF version was produced using htmldoc
. The diagrams were drawn using OmniGraffe [1]. The process was automated using Paver [2].