4. New-style object v.s. Old-Style Objects
The following presentation mainly focuses
on
new-style objects.
5. Type checking at compile-time V.S. run-time
◦ Statically typed Dynamically typed
int a a
Explicit V.S. Implicit type conversion
◦ Strongly-typed v.s. weakly-typed
Python is dynamically and strongly typed
6. <type ‘object’> is an instance of <type ‘type’>
<type ‘type’> is an instance of itself
<type ‘type’> is a subclass/subtype of <type
‘object’>
<type ‘type’>
type of all types
<type ‘object’>
bases of all other types
7. • New a type object by
subtyping
• New an object by explicit
instantiation
• The type object serves as a
factory that can churn out
new objects (to each of which
it is related as type-instance).
This is why every object has
a type.
<type ‘type’>
type of all types
<type ‘object’>
bases of all other types
<class ‘C’>
8. • Generate a ‘class’ at runtime.
• Generate a ‘function’ at runtime.
• Very flexible and generic
9. They are objects.
Not All (but most of) type objects are able to
create instance objects via the static method
__new__.
◦ type(typeObj) -> <type ‘type’>
◦ callable(typeObj) -> True
Not all (but most of) type object are
subclassable (e.g. FunctionType)
11. • All Python objects have:
– an identity (an integer, returned by id(x))
– a type (returned by type(x))
– some content/value
• Once the object is created, you cannot change
the type nor the identity. You may or may not
change the content of the object.
– Mutable object: objects whose content/value can
change
– Immutable object: objects whose content/value is
unchangeable once they are created
• ‘string’ is an object of type <type ‘str’>, and
has a unique id.
12. Names refer to objects; names are the ‘keys’
to obtain the objects. (a little bit similar to
reference type in C)
An object can have many names, or no name
at all.
Names live in namespaces (introduced in the
next slide)
They are not the properties of the object
13. • Namespaces are collections of (name, object
reference) pairs (implemented using
dictionaries).
• globals(): the namespace of the __main__
module
• The built-in namespace associated with the
execution of a code block is actually found by
looking up the name __builtins__ in its global
namespace
• Every object can have its namespace. (e.g. a
module namespace, an instance namespace, a
function’s local namespace)
14. An attribute is a way to get from one object to
another, by applying the dot operation
◦ objectName.attrName -> anotherObject
◦ objectName.attrName
objectName.__getattribute__(‘attrName')
The object and anotherObject can be of any kind, including
module, class, function/method, and all other kinds of
instance objects.
The vague hierarchy of ‘class’ and ‘object’. Class B can
include object a, and object a now can also include Class B.
15. • The object must be created or already exist
before assignment
• objectName.attrName = anotherObj
objectName.__setattr__(‘attrName’,
anotherObj)
• What does an assignment really do?
– Binding the name, and the object
– Adding a new attribute to the ‘local’ namespace
16. • Assignment one object to another object is like
copying its reference to the name. (in terms of
C language)
• It actually re-bind the name and the object, so
the object now has several names
Python: C/C++:
a: 0 at 0013FEE0 b: 5 at 0013FEDC
a: 5 at 0013FEE0 b: 5 at 0013FEDC
# before a = b
{‘a’:0, ‘b’: 5}
# after a = b
{‘a’:5, ‘b’: 5}
17. • Names are ‘references’ (implemented by
PyObject * in C) to objects.
• Assignment a literal integer object (the value
larger) to a name is to allocate a new memory
containing that value and return the reference.
Python: C/C++:
0013FEE0
0013FEE0
18. Creating an instance of a Class by calling
__new__(cls, …)
There is no way to create a new instance
without calling __new__
cls. __new__() is a static method
19. Descriptor definition: An object with a __get__() method,
and optionally __set__() and __delete__() methods,
accepting specific parameters is said to follow the
descriptor protocol.
1. d.__get__(cobj, C)
2. d.__set__(cobj, 5)
3. d.__delete__(cobj)
20. Data Descriptor:
◦ A descriptor with
both __get__() and
__set__() methods
Non-data Descriptor
◦ Descriptors with
only the __get__()
method.
- Can be hidden by
Instance attribute.
21. A function is actually a non-data descriptor.
An easier way to generate a descriptor:
property
22. • Class function and instance method are
actually different objects
• cobj.f => C.f.__get__(cobj, C)
23. • cobj.d gets the return value of __get__,
implemented in the descriptor class.
• C.__dict__[‘d’] gets the descriptor object.
• They are of course different (in general).
24. The ‘local’ namespace (mapping of ‘name’ and ‘object
reference’) is actually saved in __dict__
25. • obj.attrName -> invoking obj.__getattribute__(‘attrName’)
– If attrName is a Python-provided attribute, return it.
– Search obj.__class__.__dict__ for attrName . If it exists
and is a data-descriptor, return the descriptor result.
Search all bases of obj.__class__ for the same case.
– Search obj.__dict__ for attrName , and return if found.
If obj is a type object, search its bases too. If it is a
type object and a descriptor is found in the object or
its bases, return the descriptor result.
– Search obj.__class__.__dict__ for attrName . If it exists
and is a non-data descriptor, return the descriptor
result. If it exists, and is not a descriptor, just return it.
Search all bases of objectname.__class__ for same case.
– Raise AttributeError
26. What if Multi-Inheritance?
c.a -> ???
d.a -> ???
Why?
27. • Searching attributes in the order of __mro__
• __mro__ is a data descriptor of <type ‘type’>
• mro: Method Resolution Order
28. A more complex example
e.a -> ???
Be careful about multi-inheritance and naming
conflict
29. • If B is a subclass of A, then B should always
appear before A in all __mro__s. Let’s denote
B > A
• If C appears before D in the list of bases in a
class statement (e.g. Z(C, D)), then C > D
MRO computing principle:
• If E > F in one scenario (or one __mro__), then
it should be that E > F in all scenarios (or all
__mro__s). A: X > Y, B: Y > X,
so when C(A, B) => Conflict
30. L[E] = E + Merge(DBAO, CAO, DC)
= E + D + Merge(BA, CAO, C)
= E + D + B + Merge(A,CAO,C)
= E + D + B + C + Merge(A,AO)
= E + D + B + C + A + O
Object
B A
D C
E
33. Assignment is to re-bind the name and
object in the ‘local’ namespace. In the case,
the object names in the function are saved in
func_code.co_varnames, and
func_code.co_argcount.
Assignment cannot change the content of the
object.
38. • When returning and passing the function. Be careful
that the name conflict may cause the problem.
• Binding objects in
func_closure when
used object in the
enclosing area.
• Scopes are
determined
statically
39. • Built-in namespace is created when the Python
interpreter starts up, and is never deleted.
• The global namespace for a module is created
when the module definition is read in; normally,
module namespaces also last until the interpreter
quits
• The local namespace for a function is created
when the function is called, and deleted when the
function returns or raises an exception that is not
handled within the function. recursive
invocations each have their own local namespace
40. • import moduleName: the module object comes into
the global dictionary.
• from moduleName import someObject: the some
object comes into the global dictionary.
41. Encapsulation
◦ Public object access, but read-only by default!
◦ Outer inner scope cannot change the inner outer
scope object’s value if programmer does not
provide the interfaces methods.
◦ The only way to change the content value of the
object is to through the object itself.
45. Exception typically is a class object (of type
<type ‘type’>)
IOError
EnvironmentError TypeError
Exception
BaseException
object
StandardError
LookupError
KeyError
Exception
Inheritance
Tree
StopIterationSystemExit
46. All built-in exception objects are defined in
exceptions module
47. When an exception is not handled at all, the
interpreter terminates execution of the
program, or returns to its interactive main loop
51. In past versions of Python string exceptions were
supported. In Python 1.5 and newer versions, all
standard exceptions have been converted to class
objects and users are encouraged to do the same.
String exceptions will raise a DeprecationWarning
in Python 2.5 and newer. In future versions,
support for string exceptions will be removed.
52. We can actually catch Exception instance, and handle it.
Take IOError for example, it has args, errno, filename, message,
strerror attributes, they are all data descriptors
args defined in BaseException
errno, filename, message, strerror defined in EnvironmentError
53.
54. • Inherit ‘Exception’ class object:
• repr() returns the canonical string representation of the object.
• __str__() is called by the str built-in function and by the print
statement to compute the informal string representation of an
object
56. • L[C] = C + D + EOF + IO + ENV + S
S
EOF Env
D IO
C
Avoid Multi-inheritance
From different Exception
Type Objects
57. • The problem with this code is that it leaves the file
open for an indeterminate amount of time after
the code has finished executing. This is not an
issue in simple scripts, but can be a problem for
larger applications.
• After the statement is executed, the file f is always
closed, even if a problem was encountered while
processing the lines.
58. • The above code roughly translates into this:
• var.__exit__() records predefined clean-up actions
http://www.python.org/dev/peps/pep-0343/
60. Difference between a & b ?
a save in A.__dict__, and b save in
instanceOfA.__dict__
To rebind a’s value in A, only by Class A
object, cannot through any instances of A.
61. • List comprehension
– s = [x ** 2 for x in range(10)]
– v = [2 ** x for x in range(10)]
– zeros = [0 for I in range(10)]
• Iterator & Generator
– g = (x * 2 for x in range(1000)) => g.next(), g.next(),
g.next()
– a function which can stop whatever it is doing at an
arbitrary point in its body, return a value back to the
caller, and, later on, resume from the point it had
`frozen'