python类——黑板客老师课程学习
1、基本语法
class class_name(base_class): base_class是它继承的父类
class_var
def methods(self,args):
statements
经典类、新式类
版本2和版本3的区别,3都是新式类
首先,写法不一样:
class A: #旧式类
pass
class B(object): #新式类
pass
经典类和新式类的区别:
1)__slots__,
新式类里有这个,‘槽’的意思,对属性的一个限制,只能访问槽里边的属性。
2)继承顺序,super
3)__new__,
4)__getattribute__
可以看到:
1.A的属性比较少,B的属性比较多。
2.A可以对__slots__以外的属性赋值,B不可以。因为Python是动态的,所以可以随便往里边添加属性,但是如果有了槽之后,即有了__slots__之后,只能添加槽里边有的
东西。三个引号包括的内容在help帮助里边会显示。我们写程序的时候尽量用新式类。
2、属性和封装
2.1实例属性和类属性
class Car(object):
country=u’中国’ #类属性
def __init__(self,length,width,height,owner=None): #定义实例属性
self.owner=owner
self.length=length
self.width=width
self.height=heigth
实例属性一般定义再__init__里边,比如上边的self.owner,self.length,self.width,self.height。类属性一般定义在方法外边,比如上边的country属性。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#copyRight by heibanke class Car(object):
country = u'中国'
def __init__(self, length, width, height, owner=None):
self.owner = owner
self.length = length
self.width = width
self.height = height
self.country = "china" if __name__ == '__main__':
a = Car(1.2,1.4,1.5,u'黑板客')
b = Car(2.2,2.4,2.5,u'小张')
print a.owner, b.owner
print a.country, b.country #country访问的是实例属性 b.country = u'美国' #改变的是实例属性 print a.country, b.country #输出实例属性
print Car.country #输出类属性 print "--------------------------"
del a.country #删除a的实例属性
print a.country#因为a的实例属性别删除了,所以会找类属性,所以输出的是类属性
#del a.country
#del Car.country
#print a.country
输出为:
>>>
黑板客 小张
china china
china 美国
中国
--------------------------
中国
>>>
当我们调用a.country时,先去实例属性中找,如果有,就用实例属性的,如果没有就找类属性的。当我们用Car.country的时候,我们调用的类属性。
当我们把a的country删除之后,a的在实例属性中找不到,就会到类属性中找。而b的country没有删除,所以直接就用实例属性中的country。
2.2私有属性
不能直接访问。对类自己可见,对外不可见的。
目的:保证赋值的合理性。
两种做法:
1.__xxx 两个下划线,不能直接访问到,但可以间接访问到
2._xxx 一个下划线,可以直接访问到,但是有一个下划线提示我们直接访问是不合理的,实际上是自己提醒自己的方式
__xxx__ 两边都有两个下划线,这是系统自带的属性。
_xxx 不能用于’from module import *’ 以单下划线开头的表示的是protected类型的变量。即保护类型只能允许其本身与子类进行访问。
__xxx 双下划线的表示的是私有类型的变量。只能是允许这个类本身进行访问了。连子类也不可以
__xxx__定义的是特列方法。像__init__之类的,是系统定义的名字,我们应该避免这样命名变量
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#copyRight by heibanke class Car(object):
country = u'中国'
def __init__(self, length, width, height, owner=None):
self.__owner = owner#双下划綫,不可以直接访问 assert length>0,"length must larger than 0"
#单下划线,可以直接访问,但是此时已经提醒作者,不应该直接访问的,作者自己监督
self._length = length
self._width = width
self._height = height def getOwner(self):
return self.__owner
def setOwner(self, value):
self.__owner = value def getLength(self):
return self._length def setLength(self,value):
assert value>0,"length must larger than 0"
self._length = value if __name__ == '__main__':
a = Car(1.2,1.4,1.5,u'黑板客')
print a.getOwner() #a.setLength(-1)
2.3装饰器描述符
描述符——定义了get和set的一个对象。
编程描述符有什么好处:像取属性一样操作方法,把方法当做属性去访问。
a.setlength(-1) 这是直接用get和set方法定义的方法
a.length=-1 这是用描述符实现的
用法:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#copyRight by heibanke class Car(object):
country = u'中国'
def __init__(self, length, width, height, owner=None):
self._owner = owner
self._length = length
self._width = width
self._height = height @property #相当于get方法
def owner(self):
return self._owner
@owner.setter #相当于set方法
def owner(self, value):
self._owner = value
@owner.deleter #相当于delete方法
def owner(self):
self._owner = None @property
def length(self):
return self._length
@length.setter
def length(self, value):
assert value>0,"length must larger than 0"
self._length = value if __name__ == '__main__':
a = Car(1.2,1.4,1.5,u'黑板客')
print a.owner
del a.owner
print a.owner
a.length=-1
输出:
>>>
黑板客
None Traceback (most recent call last):
File "C:\Users\shiye\AppData\Local\Temp\property03.py", line 36, in <module>
a.length=-1
File "C:\Users\shiye\AppData\Local\Temp\property03.py", line 28, in length
assert value>0,"length must larger than 0"
AssertionError: length must larger than 0
>>> a.length=-1
@property 是get方法
@owner.setter 是set方法
@owner.deleter 是delete方法
但是出现了一个新的问题,造成了代码的冗余,因为我们每一个属性,都要定义三个这样的方法,非常的麻烦
2.4__getattr__
__getattr__ ——特殊方法
自动调用
当访问一个属性,访问不到时,它会自动调用。
__setattr__
给属性赋值的时候自动调用
__delattr__
删除属性的时候自动调用
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#copyRight by heibanke class Car(object):
country = u'中国'
__slots__=('length','width','height','owner','__dict__') def __init__(self, length, width, height, owner=None):
self.owner = owner
self.length = length
self.width = width
self.height = height def __getattr__(self,name):
print "__getattr__",name
return self.__dict__.get(name,None) def __setattr__(self,name,value):
print "__setattr__",name
if name!='owner':
assert value>0, name+" must larger than 0"
self.__dict__[name]=value def __delattr__(self,name):
print "__delattr__",name
if name=='owner':
self.__dict__[name]=None if __name__ == '__main__':
a = Car(1.2,1.4,1.5,u'黑板客')
"""
print a.owner
del a.owner
print a.owner
a.length=1 print a.country
a.country = 'china'
print a.country
"""
#a.name = u"一汽"
输出:
>>>
__setattr__ owner
__setattr__ length
__setattr__ width
__setattr__ height
>>> a.name
__getattr__ name
>>> a.lenth=a
__setattr__ lenth
>>> a.length=-4
__setattr__ length Traceback (most recent call last):
File "<pyshell#2>", line 1, in <module>
a.length=-4
File "C:/Users/shiye/Documents/set.py", line 22, in __setattr__
assert value>0, name+" must larger than 0"
AssertionError: length must larger than 0
>>> __getattr__ __members__
__getattr__ __methods__
del a.length
__delattr__ length
>>> del owner Traceback (most recent call last):
File "<pyshell#4>", line 1, in <module>
del owner
NameError: name 'owner' is not defined
>>> del a.owner
__delattr__ owner
>>>
发现没有name属性,会调用__getattr__ 函数,其他的都一样。
我们可以看到,我们只是产生了一个a,然后赋值的时候全部都调用了__setattr__,
而且我们可以在这个地方对我们要赋的值就行判断,这样就免除了在每一次赋值的时候 都要判断的麻烦。
如果我们用__slot__之后,就不会有__dict__这个东西了,就意味着无法再往里边添加__slot__以外的属性了,但是当我们把__dict__这个东西加进__slot__之后,我们,我们依然可以添加__slot__以外的属性。比如上边的例子a.name这个属性。
当我们调用a.mm的时候,因为不存在这个属性,所以会自动调用__getattr__。
这样我们就通过这些解决了,我们在设置属性时要对属性进行判断的一个过程。
但是我们为什么要用__slots__和__dict__一起来配合使用呢?
在__slots__里边加上__dict__之后,无法限制对属性的访问。如果没有slots的话,只有没有的属性才会调用__getattr__,有的属性就不会调用。而如果加上__slots__的
话,slots里边有的也会调用__getattr__。
但是这样也会有新的问题出现,如何控制对属性的赋值呢,可以用下边的方法:
我们先用assert判断一下访问的属性是否在slots里边,然后再判断,__setattr__和__delete__也要这么做
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#copyRight by heibanke class Car(object):
country = u'中国'
__slots__=('length','width','height','owner','__dict__') def __init__(self, length, width, height, owner=None):
self.owner = owner
self.length = length
self.width = width
self.height = height def __getattr__(self,name):
print "__getattr__",name
assert name in self.__slots__, "Not have this attribute "+name
return self.__dict__.get(name,None) def __setattr__(self,name,value):
print "__setattr__",name
assert name in self.__slots__, "Not have this attribute "+name if name!='owner':
assert value>0, name+" must larger than 0"
self.__dict__[name]=value def __delattr__(self,name):
print "__delattr__",name
assert name in self.__slots__, "Not have this attribute "+name
if name=='owner':
self.__dict__[name]=None if __name__ == '__main__':
a = Car(1.2,1.4,1.5,u'黑板客')
"""
print a.owner
del a.owner
print a.owner
a.length=1 print a.country
a.country = 'china'
print a.country a.name = u"一汽"
"""
大多数的时候,我们是这么用__getattr__的,,比如getattr(a,’length’)是在我们运行程序的时候才决定我们要访问哪一个属性。
2.5描述符
非数据描述符定义了一个函数:__get__
数据描述符定义两个函数:__get__ __set__
描述符可以用作描述类的属性的这样的一个东西。当你定义了__get__ __set__,之后,这个类就可以作为另一个类的属性。
举例:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#copyRight by heibanke class PositiveNum(object):
def __init__(self,value):
self.val = value def __get__(self, instance, owner):
# instance = a,b
# owner = Car
print "__get__",instance,owner
return self.val def __set__(self, instance, value):
# instance = a,b
print "__set__",instance,value
try:
assert int(value)>0
self.val = value
except AssertionError:
print "ERROR: "+str(value)+" is not positive number."
except:
print "ERROR: "+str(value)+" is not number value." def __delete__(self,instance):
print "__delete__",instance
self.val = None #def __getattribute__(self,name):
#print self, name class Car(object):
country = u'中国'
length = PositiveNum(0)
width = PositiveNum(0)
height = PositiveNum(0)
#__slots__=('owner','length','width','height') def __init__(self, length, width, height, owner=None):
self.owner = owner
self.length = length
self.width = width
self.height = height if __name__ == '__main__':
a = Car(1.2,1.4,1.5,u'黑板客')
b = Car(2.2,2.4,2.5,u'小明')
这样有一个好处,就是我们在对他进行初始化的时候,也把也进入了__init__里边对值进行了判断,免除了前边讲的冗余的问题。但是从运行结果上看,我们知道a.length和
b.length是一样的,为什么呢?因为length是个类属性。我们上边定义的那个类PositiveNum,里边有__set__和__get__函数,所以它不再是一个实例变量而是一个类变量。
怎么解决这个问题呢?
针对类修改PositiveNum
class PositiveNum(object):
def __init__(self):
self.default = 1
self.data = {} def __get__(self, instance, owner):
# instance = x
# owner = type(x)
print "__get__",instance,owner
return self.data.get(instance, self.default) def __set__(self, instance, value):
# instance = x
print "__set__",instance,value
try:
assert int(value)>0
self.data[instance] = value ###针对instance进行赋值,不同的instance有不同的值,这样就保证了是实例变量而不是类变量
except AssertionError:
print "ERROR: "+str(value)+" is not positive number."
except:
print "ERROR: "+str(value)+" is not number value." def __delete__(self,instance):
print "__delete__",instance
del self.data[instance]
实际上data是一个字典,我们针对不同的instance进行输出。但是也有一个问题,这个时候我们可以对a.x这样的属性进行赋值,实际上我们不想这样的,怎么办呢?我们可
以在Car类里边加上__slots__进行限制。
另外新式类里边多了一个__attribute__的描述符。在访问属性的时候就会被调用,所以调用的时机比较多。一般来说我们很少用的,如果改变了它,会考虑很多情况,因为
许多情况它都会被调用的。
3.方法
分类
类方法 @classmethod
实例方法
静态方法 @staticmethod
特殊方法(魔法方法) __init__等
形式上的区别:
1、调用是通过类和实例进行的,不能直接调用
2、有自己的特殊参数 self cls
3、有自己的声明语法@classmethod @staticmethod __xx__()
实质的区别:——绑定
类方法——绑定类
实例方法——绑定实例
静态方法——和函数没有区别,无绑定
特殊方法——在某些场合自动调用
方法和函数的区别:
函数(function)就相当于一个数学公式,它理论上不与其它东西关系,它只需要相关的参数就可以。所以普通的在module中定义的称谓函数是很有道理的。
方法是与某个对象相互关联的,也就是说它的实现与某个对象有关联关系。这就是方法。虽然它的定义方式和函数是一样的。也就是说,在Class定义的函数
就是方法。
静态方法和实例方法的区别主要体现在两个方面:
1. 在外部调用静态方法时,可以使用"类名.方法名"的方式,也可以使用"对象名.方法名"的方式。而实例方法只有后面这种方式。也就是说,调用静态方法可以
无需创建对象。
2. 静态方法在访问本类的成员时,只允许访问静态成员(即静态成员变量和静态方法),而不允许访问实例成员变量和实例方法;实例方法则无此限制。
3. 类方法可以被对象调用,也可以被实例调用;传入的都是类对象,主要用于工厂方法,具体的实现就交给子类处理
4. 静态方法参数没有实例参数 self, 也就不能调用实例参数
静态方法和类方法的区别:
逻辑上类方法应当只被类调用,实例方法实例调用,静态方法两者都能调用。主要区别在于参数传递上的区别,实例方法悄悄传递的是self引用作为参数,而
类方法悄悄传递的是cls引用作为参数。静态方法无隐含参数,主要为了类实例也可以直接调用静态方法。
#!/usr/bin/env python
# coding: utf-8
# http://stackoverflow.com/questions/12179271/python-classmethod-and-staticmethod-for-beginner class Date(object):
#self 作为实例参数
def __init__(self, day=0, month=0, year=0):
self.day = day
self.month = month
self.year = year def __str__(self):#用于输出的时候显示内容
return "{0}-{1}-{2}".format(self.year, self.month, self.day) # cls作为类方法的参数
@classmethod
def from_string(cls, date_as_string):
year, month, day = map(int, date_as_string.split('-'))
date1 = cls(day, month, year)
return date1 #静态方法,用类还是用实例都可以访问,这里没有self或者cls作为参数
@staticmethod
def is_date_valid(date_as_string):
year, month, day = map(int, date_as_string.split('-'))
return day <= 31 and month <= 12 and year <= 3999 @staticmethod
def millenium(month, day):
return Date(month, day, 2000) #返回的是Date对象 class DateTime(Date): #特殊方法,当我们print一个类的时候,按照__str__的方式显示出来
def __str__(self):
return "{0}-{1}-{2} - 00:00:00PM".format(self.year, self.month, self.day) if __name__=="__main__": s='2012-09-11'
if Date.is_date_valid(s):
date1 = Date.from_string('2012-09-11')
print date1
date2 = DateTime.from_string('2012-09-11')
print date2 millenium_new_year1 = Date.millenium(1, 1)
print millenium_new_year1 millenium_new_year2 = DateTime.millenium(10, 10)
print millenium_new_year2
输出:
>>>
2012-9-11
2012-9-11 - 00:00:00PM
2000-1-1
2000-10-10
>>>
特殊方法
属性访问:__getattr__,__setattr__,__getattribute__
实例生成/类生成:__init__,__new__
数字计算:__add__,__sub__,__mul__,__div__,__pow__,__round__
调用方法:__str__,__repr__,__lent__,__bool__ 可以通过函数调用的方式,比如str()的方式调用,不需要用类或者实例的方式
比较大小:__cmp__,__lt__,__le__,__eq__,__ne__,__gt__,__ge__
集合访问:__setslice__,__getslice__,__getitem__,__setitem__,__contains__
迭代器: __iter__,__next__
4、继承和组合
4.1继承——简单例子
#!/usr/bin/python
# -*- coding: utf-8 -*-
#copyRight by heibanke class Employee(object):
def __init__(self, name, job=None, pay=0): # class = data + logic
self._name = name
self._job = job
self._pay = pay
def giveRaise(self, percent):
self._pay = int(self._pay * (1 + percent))
def __str__(self):
return '[Employee: %s, %s, %s]' % (self._name, self._job, self._pay) class Manager(Employee):
def __init__(self, name, pay): # Redefine constructor
Employee.__init__(self, name, 'mgr', pay)
def giveRaise(self, percent, bonus=.10):
Employee.giveRaise(self, percent + bonus) if __name__ == '__main__':
a=Employee("xiaoli",'sw_engineer',10000)
b=Employee("xiaowang",'hw_engineer',12000)
c=Manager("xiaozhang",8000) members=[a,b,c] for member in members:
member.giveRaise(0.1)
print member
输出:
>>>
[Employee: xiaoli, sw_engineer, 11000]
[Employee: xiaowang, hw_engineer, 13200]
[Employee: xiaozhang, mgr, 9600]
>>> c.__class__
<class '__main__.Manager'>
>>> c.__class__.__base__
<class '__main__.Employee'>
>>> c.__class__.__base__.__base__
<type 'object'>
>>> c.__class__.__base__.__base__.__base__
>>>
4.2多重继承
为什么会是这样呢?
我们导入inspect来查看一下D优先继承哪些类。可以看到BAC的顺序
mro:method resolution order
经典类(classic)是深度优先
新式类(new)是广度优先
由于我们定义的是经典类,所以D先继承了B,然后继承A,然后继承C。(深度优先)
经典类和新式类的区别:
经典类定义A的时候
新式类定义A的时候
4.3super继承
当我们有多重继承的时候,会导致父类别多次调用了。
为了解决这个问题,在新式类中我们引进了super关键字(super只在新式类中有),避免父类的多次调用。
super是一个类,不是一个函数,调用规则:
super(D,self).test()。
不使用super的情况:
#!/usr/bin/python
# -*- coding: utf-8 -*-
#copyRight by heibanke class A:
def test(self):
print "A's test" class B(A):
def test(self):
print "B's test"
A.test(self)
#super(B,self).test() class C(A):
def test(self):
print "C's test"
A.test(self) class D(B,C):
def test(self):
print "D's test"
B.test(self)
C.test(self) if __name__=="__main__":
a=D()
a.test()
输出:
>>> ================================ RESTART ================================
>>>
D's test
B's test
A's test
C's test
A's test
>>>
使用super的情况:
#!/usr/bin/python
# -*- coding: utf-8 -*-
#copyRight by heibanke class A(object):
def test(self):
print "A's test" class B(A):
def test(self):
print "B's test"
super(B,self).test() class C(A):
def test(self):
print "C's test"
super(C,self).test() class D(B,C):
def test(self):
print "D's test"
super(D,self).test() if __name__=="__main__":
a=D()
a.test()
输出:
>>> ================================ RESTART ================================
>>>
D's test
B's test
C's test
A's test
>>>
4.4组合
把已有的类变成新的类属性。
通过已有的类生成新类。
#!/usr/bin/python
# -*- coding: utf-8 -*-
#copyRight by heibanke class Employee(object):
def __init__(self, name, job=None, pay=0): # class = data + logic
self._name = name
self._job = job
self._pay = pay
def giveRaise(self, percent):
self._pay = int(self._pay * (1 + percent))
def __str__(self):
return '[Employee: %s, %s, %s]' % (self._name, self._job, self._pay) class Manager(Employee):
def __init__(self, name, pay): # Redefine constructor
super(Manager,self).__init__(name, 'mgr', pay)
def giveRaise(self, percent, bonus=.10):
super(Manager,self).giveRaise(percent + bonus) class Department(object):
def __init__(self, *args):
self.members = list(args) def addMember(self, person):
self.members.append(person) def showAll(self):
for person in self.members:
print person
def giveRaise(self,percent):
for person in self.members:
person.giveRaise(percent) if __name__ == '__main__':
a=Employee("xiaoli",'sw_engineer',10000)
b=Employee("xiaowang",'hw_engineer',12000)
c=Manager("xiaozhang",8000) d=Department(a,b,c) d.showAll()
d.giveRaise(0.1)
d.showAll()
输出:
>>>
[Employee: xiaoli, sw_engineer, 10000]
[Employee: xiaowang, hw_engineer, 12000]
[Employee: xiaozhang, mgr, 8000]
[Employee: xiaoli, sw_engineer, 11000]
[Employee: xiaowang, hw_engineer, 13200]
[Employee: xiaozhang, mgr, 9600]
>>>
5、多态
多态是不同的类的相同的方法,相同的参数,不同功能。调用时便于将一组对象放在集合里,无需判断对象的具体类型,统一调用。
里氏代换原则:
父类出现的地方,子类一定可以出现,反之不一定。
重载:相同的方法的不同的参数。对应Python是args,kwargs。
最典型的是运算符重载。
6、元编程
——比较难,但是大部分不会用到它。
元(meta)
语法——》语句
类——》对象
元类——》类
元类就是生成类的类。通过元类来编程就是元编程。
元编程——type
type(name,bases,attrs)
name:类名字符串
bases:父类元组
attrs:属性字典
A=type(‘A’,(object,),{‘b’:1})
a=A()
print A, a.b
c++和python的类的概念是不一样的。c++的类就是语法,编译的时候类并没有生成,只是在语法上限制了一些东西。而Python是一个对象,是可以生成出来的,比如上边的A,是
通过编程序生成出来的。在Python里边可以通过元类生成类。
但是这样的方式让人看起来不舒服,于是Python提供另外一种方法:
class simplemeta(type):
def __init__(cls,name,bases,nmspc):
super(simplemeta,cls).__init__(name,bases,nmspc)
cls.uses_metaclass=lambda self:’yes’
写法1:
A=simplemeta(‘A’,(),{})
type也是一个类,类似于object类,type类里边的东西比object多一些。
写法2:
class A(object):
__metaclass__==simplemeta
方法2中提供了__metaclass__的关键字,让我们很清楚的知道这就是一个元类。以后尽量用方法2来写。
但是通过元类生成类和通过继承父类生成类有什么区别呢?
元类和父类的区别:
1、通过元类的初始化函数,或用metaclass关键字来生成新类
2、通过继承父类来生成新类
元类主要是定义类的行为,父类主要定义的是实例的行为。
不可继承的类——最终类
class final(type):
def __init__(cls,name,bases,namespace):
super(final,cls).__init__(name,bases,namespace)
for klass in bases:
if isinstance(klass,final):
raise TypeError(str(klass.__name__)+’is final’)
当你想定义一个最终类的时候,加上这个元类就可以了。
为什么?
因为在finla类里边,有一些属性,因为B是final生成的,所以会在klaas里边,所以当我们运行的时候,isinstance会显示B是一个final,所以就raise TypeError(……)。
new的用途——新式类里边才会有的东西。
__new__和__init__的区别:__new__是分配空间,__init__是配置参数,执行属性是先分配空间再配置参数。
我们可以看到,第一个生成正整数没有成功,第二个成功了,为什么呢?
因为__init__都已经配置好参数了,而对于int这种不可变的类型,你在对他改变是没有用的,而__new__只是分配好空间,没有产生什么值,所以就可以改变。
单例模式中用__new__可以提前判断。
class singleton(object):
def __new__(cls):
if now hasattr(cls):
cls.instance=super(singleton,cls).__new__(cls)
return cls.instance
元类的用法
抽象函数——虚函数,在子类里实现。
class MyAbstractClass(object):
def method1(self):
raise NotImplementedError(‘please Implement this method’)
但是这样用有一个问题:如果我们没有实现里边方法,当我们不用这个方法的时候,不会报错,只有当子类使用这个方法的时候才会报错,所以我们一般用下
边的方法,导进来一个abs的类。
接口,由一组抽象函数组成的类
from abs import ABCMeta,abstractmethod
from MyAbstractClass2(object):
__metaclass__=ABCMeta
@bastractmethod
def method1(self):
pass
按照这么实现,即使子类没有调用这个方法,如果他没有实现这个方法,也会报错。
注意看注释信息,报错的时机不一样的。
元编程——ORM
ORM:Object Relational Mapping对象关系映射
将数据库的操作用面向对象的程序方法实现。
匹配由ORM来产生,我们只要生成类进行操作就行了。
好处:
1、易改:便于更新数据库,sql语句是由底层根据数据库类型生成的上层数据模型无需变化。
2、易用:便于对数据模型进行操作,创建,更新,查询,删除。用户编写简单,无需写sql语句即可操作数据。
3、易看:使数据模型的程序文档化。便于维护。
缺点:
不灵活,没有sql语句强大等。
class user(model);
id=integerField(’uid’)
name=stringField(‘username’)
email=stringField(‘email’)
password=stringField(‘password’)
u=user(id=12345,name=’Michael’,email=’test@orm.org’,password=’my_pwd)
u.save()
具体内容可参考廖雪峰老师的博客学习相关的知识。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# http://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/001386820064557c69858840b4c48d2b8411bc2ea9099ba000 ' Simple ORM using metaclass ' __author__ = 'Michael Liao' class Field(object):
def __init__(self, name, column_type):
self.name = name
self.column_type = column_type
def __str__(self):
return '<%s:%s>' % (self.__class__.__name__, self.name) class StringField(Field):
def __init__(self, name):
super(StringField, self).__init__(name, 'varchar(100)') class IntegerField(Field):
def __init__(self, name):
super(IntegerField, self).__init__(name, 'bigint') class ModelMetaclass(type): def __new__(cls, name, bases, attrs):
print "name is ",name
print "bases is ",bases
print "attrs is ",attrs if name=='Model':
return type.__new__(cls, name, bases, attrs)
print('Found model: %s' % name)
mappings = dict()
for k, v in attrs.iteritems():
if isinstance(v, Field):
print('Found mapping: %s ==> %s' % (k, v))
mappings[k] = v
for k in mappings.iterkeys():
attrs.pop(k)
attrs['__mappings__'] = mappings # 保存属性和列的映射关系
attrs['__table__'] = name # 假设表名和类名一致
return type.__new__(cls, name, bases, attrs) class Model(dict):
__metaclass__ = ModelMetaclass def __init__(self, **kw):
print "Model instance __init__"
super(Model, self).__init__(**kw) def save(self):
fields = []
params = []
args = []
for k, v in self.__mappings__.iteritems():
fields.append(v.name)
params.append('%s')
args.append(self[k])
sql = 'insert into %s (%s) values (%s)' % (self.__table__, ','.join(fields), ','.join(params))
print('SQL: %s' % sql)
print('ARGS: %s' % str(args)) @classmethod
def find_all(cls, *args): sql = 'select * from %s' % cls.__table__
print('SQL: %s' % sql)
# testing code: class User(Model):
id = IntegerField('uid')
name = StringField('username')
email = StringField('email')
password = StringField('password') u1 = User(id=12345, name='Michael', email='test1@orm.org', password='my-pwd')
u2 = User(id=22345, name='Richael', email='test2@orm.org', password='my-pwd')
u3 = User(id=32345, name='Hichael', email='test3@orm.org', password='my-pwd') u1.save()
u2.save()
u3.save()
7、wxpython
python类——黑板客老师课程学习的更多相关文章
- python爬虫——黑板客老师课程学习
程序: 目标url 内容提取 表现形式 为什么: 大数据——数据膨胀,信息太多了,不知道哪些信息适合你,例如谷歌搜索引擎. 垂直行业搜索——某一个行业的搜索,与搜索引擎最大的区别:搜索引擎是告诉你哪些 ...
- python画图—黑板客老师课程学习
1.介绍 把每个图都看作一个对象,图中的每一个部分也是对象.——所有的一切都是对象. 工具——ipython notebook 是python里边用的最多的2D&3D的会图库,开源免费库,使用 ...
- python变量——黑板客老师课程学习
1.和C++.Java的区别: 动态类型:不需要声明a的类型. a=34 type(a) <type ‘int’> 一切皆对象: 4 2.数字: 自动转换类型:a=34 A=3.14 ...
- python计算机视觉——黑板客老师课程学习
机器学习的一个应用方向,是如何让机器去理解图像.包括对图像里物体的识别,跟踪和测量. 能做什么——无人驾驶汽车.人脸识别.车牌识别手势识别(游戏方向) PIL静态的库 OpenCV 动态的库 impo ...
- 线性代数和numpy——黑板客老师课程学习
一.代数是什么 代数->数的抽象表示->向量空间(线性空间) 线代->线性代数 关系: 向量空间之间和内部转换是通过线性变换. 实数——一维空间的点 复数——二维空间的点 如果两个向 ...
- python语句表达式——黑板客老师课程学习
1.赋值 多重赋值: a,b=1,2 a,b=’beijing’,’sh’ a,b=’bj’ a,b=(1,2) a,b=[1,2] …… 2.输入输出 输入: raw_input() 原始输入 ...
- pyhton函数——黑板客老师课程学习
1.基本语法 语法: def func_name (arguments) 定义 statements return x,y x,y=func_name(para) 调用 作用域: 可以给内置的函 ...
- "做中学"之“极客时间”课程学习指导
目录 "做中学"之"极客时间"课程学习指导 所有课程都可以选的课程 Java程序设计 移动平台开发 网络攻防实践 信息安全系统设计基础 信息安全专业导论 极客时 ...
- python类,魔术方法等学习&&部分ssti常见操作知识点复习加深
python类学习&&部分ssti常见操作知识点复习加深 在做ssti的模块注入的时候经常觉得自己python基础的薄弱,来学习一下,其实还是要多练习多背. 在python中所有类默认 ...
随机推荐
- python数据结构与算法——冒泡排序
用两种方式实现,非递归和递归 直接上代码: 先是失败的递归方式,涉及到对象引用的问题: # Bad 想一想为啥不行? def bubblesort_rec_bad(A): if len(A)==1: ...
- iOS的URL处理
前两天处理iOSapp过程中(我是用swift语言写的,资料较少),被一个“字符串”搞了一晚上的时间到第二天才处理好,在此记下,望见过此文的学生有一天遇到该情况能三分钟搞定不浪费时间: 先看如下代码 ...
- HDU-2222 Keywords Search(AC自动机--模板题)
题目大意:统计一共出现了多少次模板串. 题目分析:AC自动机的模板题.不过这题有坑,相同的模板串不能只算一次. 代码如下: # include<iostream> # include< ...
- python built-in delattr()
delattr(object,name) 使用此函数必须保证name是可以被删除,即先调用setattr(object,name,value) name必须是字符串并且是object的属性. 函数的作 ...
- strcat函数的使用需要注意的问题
曾被这个函数困扰了好久,然后各种假设,验证:但是最后却发现这个函数并没有什么好讲的,原来的过错一切都源于忽略了“*dst去掉\0,然后加上*src,最后返回*dst”这句话的真正含义:给*dst分配的 ...
- 【Unity3D基础教程】给初学者看的Unity教程(三):通过制作Flappy Bird了解Native 2D中的Sprite,Animation
作者:王选易,出处:http://www.cnblogs.com/neverdie/ 欢迎转载,也请保留这段声明.如果你喜欢这篇文章,请点[推荐].谢谢! 引子 上一次我们讲了MonoBehaviou ...
- C#访问非托管内存
示例1:分配一个新的内存地址给新变量 Point p; // Initialize unmanged memory to hold the struct. IntPtr pnt = Marshal.A ...
- Pandas中DateFrame修改列名
Pandas中DateFrame修改列名 在做数据挖掘的时候,想改一个DataFrame的column名称,所以就查了一下,总结如下: 数据如下: >>>import pandas ...
- Bootstrap 3 管理模板
下面这 10 个模板是从最新的 Bootstrap 3 管理模板人工挑选出来的,用来构建网站的后台管理界面,这些模板都是在最近 2 个月内发布. 1. Curo – Admin Template Cu ...
- JS--事件模块
一.JS event 的浏览器兼容 说到JS事件,不能不先讲一下事件流 1 事件流的定义:事件流是指从页面中接收事件的顺序 如下图所示,假设有四个圆层叠在一起,如果我们单击图中最里面的那个圆,那么我们 ...