Skip to content

Commit 32347c1

Browse files
committed
add metaclass samples
1 parent 2ac43de commit 32347c1

3 files changed

Lines changed: 109 additions & 0 deletions

File tree

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#!/usr/bin/env python3
2+
# -*- coding: utf-8 -*-
3+
4+
def fn(self, name='world'): # 先定义函数
5+
print('Hello, %s.' % name)
6+
7+
Hello = type('Hello', (object,), dict(hello=fn)) # 创建Hello class
8+
9+
h = Hello()
10+
print('call h.hello():')
11+
h.hello()
12+
print('type(Hello) =', type(Hello))
13+
print('type(h) =', type(h))

py3/oop_advance/orm.py

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
#!/usr/bin/env python3
2+
# -*- coding: utf-8 -*-
3+
4+
' Simple ORM using metaclass '
5+
6+
class Field(object):
7+
8+
def __init__(self, name, column_type):
9+
self.name = name
10+
self.column_type = column_type
11+
12+
def __str__(self):
13+
return '<%s:%s>' % (self.__class__.__name__, self.name)
14+
15+
class StringField(Field):
16+
17+
def __init__(self, name):
18+
super(StringField, self).__init__(name, 'varchar(100)')
19+
20+
class IntegerField(Field):
21+
22+
def __init__(self, name):
23+
super(IntegerField, self).__init__(name, 'bigint')
24+
25+
class ModelMetaclass(type):
26+
27+
def __new__(cls, name, bases, attrs):
28+
if name=='Model':
29+
return type.__new__(cls, name, bases, attrs)
30+
print('Found model: %s' % name)
31+
mappings = dict()
32+
for k, v in attrs.items():
33+
if isinstance(v, Field):
34+
print('Found mapping: %s ==> %s' % (k, v))
35+
mappings[k] = v
36+
for k in mappings.keys():
37+
attrs.pop(k)
38+
attrs['__mappings__'] = mappings # 保存属性和列的映射关系
39+
attrs['__table__'] = name # 假设表名和类名一致
40+
return type.__new__(cls, name, bases, attrs)
41+
42+
class Model(dict, metaclass=ModelMetaclass):
43+
44+
def __init__(self, **kw):
45+
super(Model, self).__init__(**kw)
46+
47+
def __getattr__(self, key):
48+
try:
49+
return self[key]
50+
except KeyError:
51+
raise AttributeError(r"'Model' object has no attribute '%s'" % key)
52+
53+
def __setattr__(self, key, value):
54+
self[key] = value
55+
56+
def save(self):
57+
fields = []
58+
params = []
59+
args = []
60+
for k, v in self.__mappings__.items():
61+
fields.append(v.name)
62+
params.append('?')
63+
args.append(getattr(self, k, None))
64+
sql = 'insert into %s (%s) values (%s)' % (self.__table__, ','.join(fields), ','.join(params))
65+
print('SQL: %s' % sql)
66+
print('ARGS: %s' % str(args))
67+
68+
# testing code:
69+
70+
class User(Model):
71+
id = IntegerField('id')
72+
name = StringField('username')
73+
email = StringField('email')
74+
password = StringField('password')
75+
76+
u = User(id=12345, name='Michael', email='test@orm.org', password='my-pwd')
77+
u.save()

py3/oop_advance/use_metaclass.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#!/usr/bin/env python3
2+
# -*- coding: utf-8 -*-
3+
4+
# metaclass是创建类,所以必须从`type`类型派生:
5+
class ListMetaclass(type):
6+
def __new__(cls, name, bases, attrs):
7+
attrs['add'] = lambda self, value: self.append(value)
8+
return type.__new__(cls, name, bases, attrs)
9+
10+
# 指示使用ListMetaclass来定制类
11+
class MyList(list, metaclass=ListMetaclass):
12+
pass
13+
14+
L = MyList()
15+
L.add(1)
16+
L.add(2)
17+
L.add(3)
18+
L.add('END')
19+
print(L)

0 commit comments

Comments
 (0)