zoukankan      html  css  js  c++  java
  • Python学习札记(四十) 面向对象编程 Object Oriented Program 11

    参考:使用元类

    NOTE:

    type()

    1.type()函数可以用于检查一个类或者变量的类型。

    #!/usr/bin/env python3
    
    class Myclass(object):
    	"""docstring for Myclass"""
    	def __init__(self):
    		super(Myclass, self).__init__()
    
    	def func(self):
    		pass
    
    def main():
    	h = Myclass()
    	print(type(h))
    
    if __name__ == '__main__':
    	main()
    
    sh-3.2# ./oop12.py 
    <class '__main__.Myclass'>
    

    class的定义是运行时动态创建的,而创建class的方法就是使用type()函数。

    2.因此,我们可以通过type()函数在运行时动态创建一个类,这是动态语言的一个特点:

    	NewClass = type('NewClass', (Myclass,), dict(func=run))
    	h1 = NewClass()
    	h1.func()
    
    running
    

    创建一个对象,需要给type()函数传入三个参数:

    type(name, bases, dict) -> a new class
    

    第一个是类名,第二个是继承的基类,第三个是绑定该类中的函数。

    通过type()函数创建的类完全和用class关键字声明的类一样,因为Python解释器遇到class定义的时候,也是通过type()方法来定义一个类的。

    type()方法支持动态创建一个类,也就是说,动态语言本身支持运行时动态创建类,这与静态语言有非常大的不同。

    metaclass

    元类本身而言,它们其实是很简单的:

    1)拦截类的创建

    2)修改类

    3)返回修改之后的类

    1.元(猿)类:是我们创建类的模板。

    创建一个对象时,我们需要依据它的类进行创建;创建一个类的时候,我们需要依据它的元类来进行创建。

    也就是说,可以把类看成是metaclass创建出来的“实例”。

    #!/usr/bin/env python3
    
    class Listmetaclass(type):
    	"""docstring for Listmetaclass"""
    	def __new__(cls, name, bases, attrs):
    		attrs['add'] = lambda self, value: self.append(value)
    		return type.__new__(cls, name, bases, attrs)
    
    class NewClass(list, metaclass=Listmetaclass): # 指示解释器在创建类的时候通过元类的__new__()创建
    	pass
    
    def main():
    	h = NewClass()
    	h.add(1)
    	print(h)
    
    if __name__ == '__main__':
    	main()
    
    sh-3.2# ./oop13.py 
    [1]
    

    事实上,将函数add直接写在一个继承的子类中会好很多,这是一个十分难懂的点。

    2.特殊情况:“Object Relational Mapping”,即对象-关系映射。

    #!/usr/bin/env python3
    
    class Field(object):
    	"""docstring for Field"""
    	def __init__(self, name, column_type):
    		super(Field, self).__init__()
    		self.name = name
    		self.column_type = column_type
    		
    	def __str__(self):
    		print('<%s:%s>' % (self.__class__.__name__, self.name))
    
    class IntegerField(Field):
    	"""docstring for IntegerField"""
    	def __init__(self, name):
    		super(IntegerField, self).__init__(name, 'int')
    		
    class StringField(Field):
    	"""docstring for StringField"""
    	def __init__(self, name):
    		super(StringField, self).__init__(name, 'string')
    
    class Modelmetaclass(type): # type
    	"""docstring for Modelmetaclass"""
    	def __new__(cls, name, bases, attrs):
    		if name == 'Model':
    			return type.__new__(cls, name, bases, attrs)
    		print('Found name:%s' % name)
    		mappings = dict() # save mappings of attributes
    		for i, j in attrs.items():
    			if isinstance(j, Field):
    				print('mapping: %s ==> %s' % (i, j))
    				mappings[i] = j # name i => 'Field'
    		for i in mappings.keys():
    			attrs.pop(i) # delete attrs that have been transfer to 'Field'
    		attrs['__mappings__'] = mappings 
    		attrs['__table__'] = name 
    		return type.__new__(cls, name, bases, attrs)
    
    class Model(dict, metaclass=Modelmetaclass):
    	"""docstring for Model"""
    	# reuse the old definitions of functions
    	def __init__(self, **kw):
    		super(Model, self).__init__(**kw)
    		
    	def __getattr__(self, key):
    		try:
    			return self[key]
    		except KeyError:
    			raise AttributeError(r"'Model' object has no attribute '%s'" % key)
    
    	def __setattr__(self, key, value):
    		self[key] = value
    
    	def save(self):
    		fields = []
    		params = []
    		args = []
    		for k, v in self.__mappings__.items():
    			fields.append(v.name)
    			params.append('?')
    			args.append(getattr(self, k, None))
    		sql = 'insert into %s (%s) values (%s)' % (self.__table__, ','.join(fields), ','.join(params))
    		print('SQL: %s' % sql)
    		print('ARGS: %s' % str(args))
    
    # User provide the interfaces
    class User(Model):
    	id = IntegerField('id')
    	name = StringField('username')
    	email = StringField('email')
    	password = StringField('password')
    
    def main():
    	# Create an object
    	u = User(id=9, name='Wasdns', email='952693358@qq.com', password='1234567')
    	# Save the object in the Database
    	u.save()
    
    if __name__ == '__main__':
    	main()
    

    具体解释请参考原文“美3333333”的回答。

    2017.3.10

  • 相关阅读:
    django--orm---006
    django--orm---005
    django--orm---004
    django--orm---003
    jmeter连接数据库
    django--view---001
    django--orm---002
    django--model--orm001-- 增删改查
    java并发编程
    jvm
  • 原文地址:https://www.cnblogs.com/qq952693358/p/6533363.html
Copyright © 2011-2022 走看看