Python Metaprogramming
目录

Python Metaprogramming

  • metaclass: only(?) type object
  • new style class: __metaclass__ is type
  • classic class: __metaclass__ is types.ClassType
  • instance: __class__ is class

objects:

  • class/type objects:
  • __class__ is type, all class objects are instances of type
  • __bases__: all class objects are subclasses of object
  • __metaclass__: is used to create class object if defined, or Python will use type to create class object
  • instance objects
  • __class__ is class/type object
  • function objects
  • module objects

Data Model

object:

  • identity: is, id()
  • type: type(), built-in types
  • one or more bases: base/super class
  • value
  • mutable: dicts, lists, sets
  • immutable: numbers, strings, typles

dir() list all attributes present on object

built-in types:

  • None
  • NotImplemented
  • Ellipsis: ...
  • numbers.*
  • Integral: plain integers, long integers, booleans
  • Real: double precision floating point numbers
  • Complex: two Real part of a complex number
  • Sequences
  • Immutable sequences:
  • Strings: 8-bit bytes
  • Unicode: 16/32-bit bytes
  • Tuples
  • Mutable sequences:
  • Lists:
  • ByteArrays:
  • Set
  • Sets: mutable
  • Frozen sets: immutable and hashable
  • Mappings
  • Dict
  • Callable
  • User-defined functions
  • User-defined methods
  • Generator functions: yeild
  • Built-in functions
  • Built-in methods
  • Class Types: __new__() and __init__()
  • Classic Classes: __init__()
  • Class instances: __call__()
  • Modules: __dict__()
  • Classes
  • Files
  • Internal types:
  • code objects
  • frame objects
  • traceback objects
  • slice objects
  • static method objects
  • class method objects

Callable/Functions mode

User-defined functions:

  • __doc__/func_doc
  • __name__/func_name
  • __module__
  • __defaults__/func_defaults: a tuple containing default argument values
  • __code__/func_code
  • __globals__/func_globals
  • __dict__/func_dict: The namespace supporting arbitrary function attributes.
  • __closure__/func_closure

User-defined methods:

  • im_self: class instance object
  • im_func: function object
  • im_class: class object

Class Mode

class:

  • __name__
  • __module__
  • __dict__: class's namespace
  • __bases__: ordered tuple for base class list
  • __doc__

class search path:

  • current class __dict__
  • base class
  • old style: depth-first, left-to-right
  • new style: C3 method resolution order

A class object can be called to yield a class instance.

class instance:

  • __dict__: instance own namespace

class instance search path:

  • instance namespace
  • class namespace
  • base class namespace

__class__:

__delattr__: __doc__: __format__: __getattribute__: __hash__: __init__: __new__:

__reduce__: __reduce_ex__:

__repr__: __str__:

__setattr__: __sizeof__: __subclasshook__:

所有的都是object,instance是一种类型,type也是一种类型。 Python does not distinguish between properties and methods

general object method:

Method Overloads Comment
__new__ new函数 创建instance并返回,可用于immutable类型instance创建
__init__ 构造函数 instance初始化
__del__ 析构函数 instance销毁
__repr__ 打印转换 “official” string, debug, 可代替__str__
__str__ 打印转换 “informal” string
__unicode__ unicode输出 返回unicode对象
__lt__ 小于 X<Y
__le__ 小于等于 X<=Y
__eq__ 等于 X=Y
__ne__ 不等于 X!=Y
__gt__ 大于 X>Y
__ge__ 大于等于 X>=Y
__cmp__ 比较 X==Y,X<Y
__hash__ 哈希值 __cmp____eq__组合;用户定义类型返回的值从id()而来
__nonzero__ 真值测试 如果没定义,则调用__len__

built-in attribute access method:

Method Overloads Comment
__getattr__ 返回属性值
__getattribute__ 返回属性值 适用于new-style class, 先于getattr调用
__setattr__ 设置属性值 self.dict[name] = value
__delattr__ 删除属性 del obj.name调用此方法
Method Overloads Comment
__get__
__set__
__del__

| add | + | Y,X+=Y | | or | 或操作 | |

| call | 调用函数 | X() | | getattr | 限制 | X.undefine | | setattr | 取值 | X.any=value | | getitem | 索引 | X[key] | | len | 长度 | len(X) |

| radd | Right-Side + | +X | | iadd | += | X+=Y | | iter | 迭代 | For In |

immutable类型不应该同时实现hashcmp/eq

Method Overloads Call for
__init__ 构造函数 X=Class()
__del__ 析构函数 对象销毁
__add__ + X+Y,X+=Y
__or__ | X|Y,X|=Y
__repr__ 打印转换 print X,repr(X)
__str__ 打印转换 print X,str(X)
__call__ 调用函数 X()
__getattr_ 限制 X.undefine
__setattr__ 取值 X.any=value
__getitem__ 索引 X[key],
__len__ 长度 len(X)
__cmp__ 比较 X==Y,X
__lt__ 小于 X
__eq__ 等于 X=Y
__radd__ Right-Side + +X
__iadd__ += X+=Y
__iter__ 迭代 For In

New style class vs. Old style class

# old style class existed in Python 2.1 and before
# type of `OldStyle1` is `classobj`
class OldStyle1:
pass
o = OldStyle1()

# new style class
# type of `NewStyle1` is `type`
class NewStyle1(object):
pass
n = NewStyle1()
  1. type() and __class__

  2. o.__class__ is OldStyle1, but type(o) is always <type 'instance'>.

  3. both n.__class__ and type(n) is NewStype1
>>> o.__class__
<class __main__.OldStyle1 at 0x7f2378b04738>
>>> type(o)
<type 'instance'>
>>>
>>> n.__class__
<class '__main__.NewStyle1'>
>>> type(n)
<class '__main__.NewStyle1'>
  1. super added

  2. __slots__ added

我们并不能简单地从定义的形式上来判断一个类是新式类还是古典类,而应当通过元类的类型来确定类的类型:古典类的元类为types.ClassType,新式类的元类为type类。

exec, execfile, eval, compile

everything in python is a object

New style classes always have object at the top of their inheritance chain

class Foo(object): pass Foo.mro (Foo, object) class Foo: pass Foo,mro Error

in python classes are also objects

int.class type

whenever we want to build an instance of an object two things happen: a new object of the desired type is created: new the new object can then be initialized: init

METACLASSES

since classes are just objectsmetaclasses are the way to customize their creation the base metaclass is type type's type is type a metaclass can be any class that inherits from type and overrides either new or init to provide custom behavior

a custom metaclass can be explicitly set on the class itself like so

class MyClass(object): metaclass = MyMeta

The lookup order for a metaclass is as follows: on the class in the parents in the package

作用域

作用域,遵循LEGB法则按照以下顺序搜索:

  • 局部作用域: locals(),在函数调用时创建的变量
  • 嵌套作用域: 上一层函数的作用域
  • 全局作用域: globals(),当前文件定义或import的变量
  • 内置作用域: __builtin__

注意,在Python2中,如果在函数中变量进行了赋值,则变量认为是局部作用域中的变量,不会搜索其它作用域; 如果变量声明了global,则认为是全局作用域内的变量。 以上两种情况都不会搜索到嵌套作用域,因此不能修改上一层嵌套作用域内的变量。 Python3引入了nonlocal来解决。

发表评论