1.类、对象、方法、实例
①.字段
字段包括:普通字段和静态字段,他们在定义和使用中有所区别,而最本质的区别是内存中保存的位置不同。
class Province: # 静态字段 country = ‘中国‘ def __init__(self, name): # 普通字段 self.name = name # 直接访问普通字段 obj = Province(‘河北省‘) print obj.name # 直接访问静态字段 Province.country
②.方法
方法包括:普通方法、静态方法和类方法,三种方法在内存中都归属于类,区别在于调用方式不同。
class Foo: def __init__(self, name): self.name = name def ord_func(self): """ 定义普通方法,至少有一个self参数 """ # print self.name print ‘普通方法‘ @classmethod def class_func(cls): """ 定义类方法,至少有一个cls参数 """ print ‘类方法‘ @staticmethod def static_func(): """ 定义静态方法 ,无默认参数""" print ‘静态方法‘ # 调用普通方法 f = Foo() f.ord_func() # 调用类方法 Foo.class_func() # 调用静态方法 Foo.static_func()
# 创建类 class Foo: def Bar(self): print ‘Bar‘ def Hello(self, name): print ‘i am %s‘ %name obj = Foo() # 根据类Foo创建对象obj obj.Bar() # 执行Bar方法 obj.Hello(‘Bob‘) # 执行Hello方法
③.属性
Python中的属性其实是普通方法的变形。
(1)属性的定义及使用
# ############### 定义 ############### class Foo: def func(self): pass # 定义属性 @property def prop(self): pass # ############### 调用 ############### foo_obj = Foo() foo_obj.func() foo_obj.prop #调用属性
属性的定义和调用注意事项:
注意:属性存在意义是:访问属性时可以制造出和访问字段完全相同的假象
属性由方法变种而来,如果Python中没有属性,方法完全可以代替其功能。
实例:
对于主机列表页面,每次请求不可能把数据库中的所有内容都显示到页面上,而是通过分页的功能局部显示,
所以在向数据库中请求数据时就要显示的指定获取从第m条到第n条的所有数据(即:limit m,n),这个分页的功能包括:
# ############### 定义 ############### class Pager: def __init__(self, current_page): # 用户当前请求的页码(第一页、第二页...) self.current_page = current_page # 每页默认显示10条数据 self.per_items = 10 @property def start(self): val = (self.current_page - 1) * self.per_items return val @property def end(self): val = self.current_page * self.per_items return val # ############### 调用 ############### p = Pager(1) p.start 就是起始值,即:m p.end 就是结束值,即:n
Python的属性的功能是:属性内部进行一系列的逻辑计算,最终将计算结果返回。
(2)属性的两种定义方式
# ############### 定义 ############### class Goods: @property def price(self): return "wupeiqi" # ############### 调用 ############### obj = Goods() result = obj.price # 自动执行 @property 修饰的 price 方法,并获取方法的返回值
# ############### 定义 ############### class Goods(object): @property def price(self): print ‘@property‘ @price.setter def price(self, value): print ‘@price.setter‘ @price.deleter def price(self): print ‘@price.deleter‘ # ############### 调用 ############### obj = Goods() obj.price # 自动执行 @property 修饰的 price 方法,并获取方法的返回值 obj.price = 123 # 自动执行 @price.setter 修饰的 price 方法,并将 123 赋值给方法的参数 del obj.price # 自动执行 @price.deleter 修饰的 price 方法
新式类中具有三种访问方式,可分别将三个方法定义为对同一个属性:获取、修改、删除
class Goods(object): def __init__(self): # 原价 self.original_price = 100 # 折扣 self.discount = 0.8 @property def price(self): # 实际价格 = 原价 * 折扣 new_price = self.original_price * self.discount return new_price @price.setter def price(self, value): self.original_price = value @price.deltter def price(self, value): del self.original_price obj = Goods() obj.price # 获取商品价格 obj.price = 200 # 修改商品原价 del obj.price # 删除商品原价
当使用静态字段的方式创建属性时,经典类和新式类无区别
class Foo: def get_bar(self): return ‘wupeiqi‘ BAR = property(get_bar) obj = Foo() reuslt = obj.BAR # 自动调用get_bar方法,并获取方法的返回值 print reuslt
property的构造方法中有个4个参数:
对象.属性
时自动触发执行方法对象.属性 = XXX
时自动触发执行方法del 对象.属性
时自动触发执行方法对象.属性.__doc__
,此参数是该属性的描述信息class Foo: def get_bar(self): return ‘wupeiqi‘ # *必须两个参数 def set_bar(self, value): return return ‘set value‘ + value def del_bar(self): return ‘wupeiqi‘ BAR = property(get_bar, set_bar, del_bar, ‘description...‘) obj = Foo() obj.BAR # 自动调用第一个参数中定义的方法:get_bar obj.BAR = "alex" # 自动调用第二个参数中定义的方法:set_bar方法,并将“alex”当作参数传入 del Foo.BAR # 自动调用第三个参数中定义的方法:del_bar方法 obj.BAE.__doc__ # 自动获取第四个参数中设置的值:description...
静态字段方式创建属性具有三种访问方式,我们可以根据他们几个属性的访问特点,分别将三个方法定义为对同一个属性:获取、修改、删除
class Goods(object): def __init__(self): # 原价 self.original_price = 100 # 折扣 self.discount = 0.8 def get_price(self): # 实际价格 = 原价 * 折扣 new_price = self.original_price * self.discount return new_price def set_price(self, value): self.original_price = value def del_price(self, value): del self.original_price PRICE = property(get_price, set_price, del_price, ‘价格属性描述...‘) obj = Goods() obj.PRICE # 获取商品价格 obj.PRICE = 200 # 修改商品原价 del obj.PRICE # 删除商品原价
2.类成员修饰符
对于每一个类的成员而言都有两种形式:
class C: def __init__(self): self.name = ‘公有字段‘ self.__foo = "私有字段"
私有成员和公有成员的访问限制不同:
静态字段
class C: name = "公有静态字段" def func(self): print C.name class D(C): def show(self): print C.name C.name # 类访问 obj = C() obj.func() # 类内部可以访问 obj_son = D() obj_son.show() # 派生类中可以访问
class C: __name = "公有静态字段" def func(self): print C.__name class D(C): def show(self): print C.__name C.__name # 类访问 ==> 错误 obj = C() obj.func() # 类内部可以访问 ==> 正确 obj_son = D() obj_son.show() # 派生类中可以访问 ==> 错误
普通字段
class C: def __init__(self): self.foo = "公有字段" def func(self): print self.foo # 类内部访问 class D(C): def show(self): print self.foo # 派生类中访问 obj = C() obj.foo # 通过对象访问 obj.func() # 类内部访问 obj_son = D(); obj_son.show() # 派生类中访问
class C: def __init__(self): self.__foo = "私有字段" def func(self): print self.foo # 类内部访问 class D(C): def show(self): print self.foo # 派生类中访问 obj = C() obj.__foo # 通过对象访问 ==> 错误 obj.func() # 类内部访问 ==> 正确 obj_son = D(); obj_son.show() # 派生类中访问 ==> 错误
方法、属性的访问于上述方式相似,即:私有成员只能在类内部使用
ps:非要访问私有属性的话,可以通过 对象._类__属性名
3.类的特殊成员
class Foo: """ 描述类信息,这是用于看片的神奇 """ def func(self): pass print Foo.__doc__ #输出:类的描述信息
from lib.aa import C obj = C() print obj.__module__ # 输出 lib.aa,即:输出模块 print obj.__class__ # 输出 lib.aa.C,即:输出类
class Foo: def __init__(self, name): self.name = name self.age = 18 obj = Foo(‘wupeiqi‘) # 自动执行类中的 __init__ 方法
class Foo: def __del__(self): pass
class Foo: def __init__(self): pass def __call__(self, *args, **kwargs): print ‘__call__‘ obj = Foo() # 执行 __init__ obj() # 执行 __call__
class Province: country = ‘China‘ def __init__(self, name, count): self.name = name self.count = count def func(self, *args, **kwargs): print ‘func‘ # 获取类的成员,即:静态字段、方法、 print Province.__dict__ # 输出:{‘country‘: ‘China‘, ‘__module__‘: ‘__main__‘, ‘func‘: <function func at 0x10be30f50>, ‘__init__‘: <function __init__ at 0x10be30ed8>, ‘__doc__‘: None} obj1 = Province(‘HeBei‘,10000) print obj1.__dict__ # 获取 对象obj1 的成员 # 输出:{‘count‘: 10000, ‘name‘: ‘HeBei‘} obj2 = Province(‘HeNan‘, 3888) print obj2.__dict__ # 获取 对象obj1 的成员 # 输出:{‘count‘: 3888, ‘name‘: ‘HeNan‘}
__str__:如果一个类中定义了__str__方法,那么在打印 对象 时,默认输出该方法的返回值
class Foo: def __str__(self): return ‘wupeiqi‘ obj = Foo() print obj # 输出:wupeiqi
#!/usr/bin/env python # -*- coding:utf-8 -*- class Foo(object): def __getitem__(self, key): print ‘__getitem__‘,key def __setitem__(self, key, value): print ‘__setitem__‘,key,value def __delitem__(self, key): print ‘__delitem__‘,key obj = Foo() result = obj[‘k1‘] # 自动触发执行 __getitem__ obj[‘k2‘] = ‘wupeiqi‘ # 自动触发执行 __setitem__ del obj[‘k1‘] # 自动触发执行 __delitem__
__getslice__、__setslice__、__delslice__:该三个方法用于分片操作,如:列表
#!/usr/bin/env python # -*- coding:utf-8 -*- class Foo(object): def __getslice__(self, i, j): print ‘__getslice__‘,i,j def __setslice__(self, i, j, sequence): print ‘__setslice__‘,i,j def __delslice__(self, i, j): print ‘__delslice__‘,i,j obj = Foo() obj[-1:1] # 自动触发执行 __getslice__ obj[0:1] = [11,22,33,44] # 自动触发执行 __setslice__ del obj[0:2] # 自动触发执行 __delslice__
__iter__:用于迭代器,之所以列表、字典、元组可以进行for循环,是因为类型内部定义了 __iter__
#!/usr/bin/env python # -*- coding:utf-8 -*- class Foo(object): def __init__(self, sq): self.sq = sq def __iter__(self): return iter(self.sq) obj = Foo([11,22,33,44]) for i in obj: print i
class MyType(type): def __init__(self, what, bases=None, dict=None): super(MyType, self).__init__(what, bases, dict) def __call__(self, *args, **kwargs): obj = self.__new__(self, *args, **kwargs) self.__init__(obj) class Foo(object): __metaclass__ = MyType def __init__(self, name): self.name = name def __new__(cls, *args, **kwargs): return object.__new__(cls, *args, **kwargs) # 第一阶段:解释器从上到下执行代码创建Foo类 # 第二阶段:通过Foo类创建obj对象 obj = Foo()
4.面向对象三大特性
面向对象的三大特性是指:封装、继承和多态
1)封装:
使用面向对象的封装特性时,需要:将内容封装到某处;从某处调用被封装的内容。
第①步:将内容封装到某处
self 是一个形式参数,当执行 obj1 = Foo(‘Bob‘, 18 ) 时,self 等于 obj1
当执行 obj2 = Foo(‘Paul‘, 78 ) 时,self 等于 obj2
所以,内容其实被封装到了对象 obj1 和 obj2 中,每个对象中都有 name 和 age 属性。
第②步:从某处调用被封装的内容
调用被封装的内容时,有两种情况:
class Foo: def __init__(self, name, age): self.name = name self.age = age obj1 = Foo(‘wupeiqi‘, 18) print obj1.name # 直接调用obj1对象的name属性 print obj1.age # 直接调用obj1对象的age属性 obj2 = Foo(‘alex‘, 73) print obj2.name # 直接调用obj2对象的name属性 print obj2.age # 直接调用obj2对象的age属性
class Foo: def __init__(self, name, age): self.name = name self.age = age def detail(self): print self.name print self.age obj1 = Foo(‘wupeiqi‘, 18) obj1.detail() # Python默认会将obj1传给self参数,即:obj1.detail(obj1),
所以,此时方法内部的 self = obj1,即:self.name 是 wupeiqi ;self.age 是 18 obj2 = Foo(‘alex‘, 73) obj2.detail() # Python默认会将obj2传给self参数,即:obj1.detail(obj2),
所以,此时方法内部的 self = obj2,即:self.name 是 alex ; self.age 是 78
因此,对于面向对象的封装来说,其实就是使用构造方法将内容封装到 对象中,然后通过对象直接或者self间接获取被封装的内容。
2)继承
定义一个class类的时候,可从现有的class类中继承,新的class称为子类,而被继承的class称为基类、父类或超类
class Animal: def eat(self): print "%s 吃 " %self.name def drink(self): print "%s 喝 " %self.name def shit(self): print "%s 拉 " %self.name def pee(self): print "%s 撒 " %self.name class Cat(Animal): def __init__(self, name): self.name = name self.breed = ‘猫‘ def cry(self): print ‘喵喵叫‘ class Dog(Animal): def __init__(self, name): self.name = name self.breed = ‘狗‘ def cry(self): print ‘汪汪叫‘ # ######### 执行 ######### c1 = Cat(‘小白家的小黑猫‘) c1.eat() c2 = Cat(‘小黑的小白猫‘) c2.drink() d1 = Dog(‘胖子家的小瘦狗‘) d1.eat()
因此,对于面向对象的继承来说,其实就是将多个类共有的方法提取到父类中,子类仅需继承父类而不必一一实现每个方法。
注:子类又称为 派生类 ,父类又称为 基类 。
class D(object): def bar(self): print ‘D.bar‘ class C(D): def bar(self): print ‘C.bar‘ class B(D): def bar(self): print ‘B.bar‘ class A(B, C): def bar(self): print ‘A.bar‘ a = A() # 执行bar方法时 # 首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去C类中找,如果C类中么有,则继续去D类中找,如果还是未找到,则报错 # 所以,查找顺序:A --> B --> C --> D # 在上述查找bar方法的过程中,一旦找到,则寻找过程立即中断,便不会再继续找了 a.bar()
3)多态
5.其他
class Foo(object): pass obj = Foo() isinstance(obj, Foo)
class Foo(object): pass class Bar(Foo): pass issubclass(Bar, Foo)
三、异常处理
1.异常处理基础
try: pass except Exception,ex: pass
2.常用异常处理
ArithmeticError
AssertionError
AttributeError
BaseException
BufferError
BytesWarning
DeprecationWarning
EnvironmentError
EOFError
Exception
FloatingPointError
FutureWarning
GeneratorExit
ImportError
ImportWarning
IndentationError
IndexError
IOError
KeyboardInterrupt
KeyError
LookupError
MemoryError
NameError
NotImplementedError
OSError
OverflowError
PendingDeprecationWarning
ReferenceError
RuntimeError
RuntimeWarning
StandardError
StopIteration
SyntaxError
SyntaxWarning
SystemError
SystemExit
TabError
TypeError
UnboundLocalError
UnicodeDecodeError
UnicodeEncodeError
UnicodeError
UnicodeTranslateError
UnicodeWarning
UserWarning
ValueError
Warning
ZeroDivisionError
异常类只能用来处理指定的异常情况,如果非指定异常则无法处理:
# 未捕获到异常,程序直接报错 s1 = ‘hello‘ try: int(s1) except IndexError,e: print e
写程序时需要考虑到try代码块中可能出现的任意异常,可以这样写:
s1 = ‘hello‘ try: int(s1) except IndexError,e: print e except KeyError,e: print e except ValueError,e: print e
万能异常 在python的异常中,有一个万能异常:Exception,他可以捕获任意异常,即:
s1 = ‘hello‘ try: int(s1) except Exception,e: print e
并非有这个万能异常,其他异常均可忽略,对于特殊处理或提醒的异常需要先定义,最后定义Exception来确保程序正常运行
s1 = ‘hello‘ try: int(s1) except KeyError,e: print ‘键错误‘ except IndexError,e: print ‘索引错误‘ except Exception, e: print ‘错误‘
3.其他异常处理结构
try: # 主代码块 pass except KeyError,e: # 异常时,执行该块 pass else: # 主代码块执行完,执行该块 pass finally: # 无论异常与否,最终执行该块 pass
4.主动出发异常
try: raise Exception(‘错误了。。。‘) except Exception,e: print e
5.自定义异常
class WupeiqiException(Exception): def __init__(self, msg): self.message = msg def __str__(self): return self.message try: raise WupeiqiException(‘我的异常‘) except WupeiqiException,e: print e
6.断言
# assert 条件 assert 1 == 1 assert 1 == 2
四、反射
python中的反射功能是由以下四个内置函数提供:hasattr、getattr、setattr、delattr,
四个函数分别用于对对象内部执行:检查是否含有某成员、获取成员、设置成员、删除成员。
class Foo(object): def __init__(self): self.name = ‘wupeiqi‘ def func(self): return ‘func‘ obj = Foo() # #### 检查是否含有成员 #### hasattr(obj, ‘name‘) hasattr(obj, ‘func‘) # #### 获取成员 #### getattr(obj, ‘name‘) getattr(obj, ‘func‘) # #### 设置成员 #### setattr(obj, ‘age‘, 18) setattr(obj, ‘show‘, lambda num: num + 1) # #### 删除成员 #### delattr(obj, ‘name‘) delattr(obj, ‘func‘)
#!/usr/bin/env python #coding:utf-8 from wsgiref.simple_server import make_server class Handler(object): def index(self): return ‘index‘ def news(self): return ‘news‘ def RunServer(environ, start_response): start_response(‘200 OK‘, [(‘Content-Type‘, ‘text/html‘)]) url = environ[‘PATH_INFO‘] temp = url.split(‘/‘)[1] obj = Handler() is_exist = hasattr(obj, temp) if is_exist: func = getattr(obj, temp) ret = func() return ret else: return ‘404 not found‘ if __name__ == ‘__main__‘: httpd = make_server(‘‘, 8001, RunServer) print "Serving HTTP on port 8000..." httpd.serve_forever()
#!/usr/bin/env python # -*- coding:utf-8 -*- import sys def s1(): print ‘s1‘ def s2(): print ‘s2‘ this_module = sys.modules[__name__] hasattr(this_module, ‘s1‘) getattr(this_module, ‘s2‘)
结论:反射是通过字符串的形式操作对象相关的成员。一切事物都是对象。
五、练习
1.单例模式:创建三个游戏人物
要求:
# ##################### 定义类 ##################### class Person: def __init__(self, na, gen, age, fig): self.name = na self.gender = gen self.age = age self.fight =fig def grassland(self): """注释:草丛战斗,消耗200战斗力""" self.fight = self.fight - 200 # ##################### 创建实例 ##################### cang = Person(‘小A‘, ‘女‘, 18, 1000) dong = Person(‘小B‘, ‘男‘, 20, 1800) bo = Person(‘小C‘, ‘女‘, 19, 2500)
2.单例模式:创建对数据库操作的公共类
# #### 定义类 #### class DbHelper(object): def __init__(self): self.hostname = ‘1.1.1.1‘ self.port = 3306 self.password = ‘pwd‘ self.username = ‘root‘ def fetch(self): # 连接数据库 # 拼接sql语句 # 操作 pass def create(self): # 连接数据库 # 拼接sql语句 # 操作 pass def remove(self): # 连接数据库 # 拼接sql语句 # 操作 pass def modify(self): # 连接数据库 # 拼接sql语句 # 操作 pass # #### 操作类 #### db = DbHelper() db.create()
3.结合2,实现Web应用程序
#!/usr/bin/env python #coding:utf-8 from wsgiref.simple_server import make_server class DbHelper(object): def __init__(self): self.hostname = ‘1.1.1.1‘ self.port = 3306 self.password = ‘pwd‘ self.username = ‘root‘ def fetch(self): # 连接数据库 # 拼接sql语句 # 操作 return ‘fetch‘ def create(self): # 连接数据库 # 拼接sql语句 # 操作 return ‘create‘ def remove(self): # 连接数据库 # 拼接sql语句 # 操作 return ‘remove‘ def modify(self): # 连接数据库 # 拼接sql语句 # 操作 return ‘modify‘ class Handler(object): def index(self): # 创建对象 db = DbHelper() db.fetch() return ‘index‘ def news(self): return ‘news‘ def RunServer(environ, start_response): start_response(‘200 OK‘, [(‘Content-Type‘, ‘text/html‘)]) url = environ[‘PATH_INFO‘] temp = url.split(‘/‘)[1] obj = Handler() is_exist = hasattr(obj, temp) if is_exist: func = getattr(obj, temp) ret = func() return ret else: return ‘404 not found‘ if __name__ == ‘__main__‘: httpd = make_server(‘‘, 8001, RunServer) print "Serving HTTP on port 8001..." httpd.serve_forever()
每个请求到来,都需要在内存里创建一个实例,再通过该实例执行指定的方法
问题:
如果并发量大,内存里就会存在非常多功能上一模一样的对象。这些对象肯定会消耗内存,对于这些功能相同的对象可以在内存中仅创建一个,需要时都去调用
单例模式用来保证内存中仅存在一个实例
通过面向对象的特性,构造出单例模式: # ########### 单例类定义 ########### class Foo(object): __instance = None @staticmethod def singleton(): if Foo.__instance: return Foo.__instance else: Foo.__instance = Foo() return Foo.__instance # ########### 获取实例 ########### obj = Foo.singleton()
Python单例模式,创建对象时不能再直接使用:obj = Foo(),而应该调用特殊的方法:obj = Foo.singleton()
#!/usr/bin/env python #coding:utf-8 from wsgiref.simple_server import make_server # ########### 单例类定义 ########### class DbHelper(object): __instance = None def __init__(self): self.hostname = ‘1.1.1.1‘ self.port = 3306 self.password = ‘pwd‘ self.username = ‘root‘ @staticmethod def singleton(): if DbHelper.__instance: return DbHelper.__instance else: DbHelper.__instance = DbHelper() return DbHelper.__instance def fetch(self): # 连接数据库 # 拼接sql语句 # 操作 pass def create(self): # 连接数据库 # 拼接sql语句 # 操作 pass def remove(self): # 连接数据库 # 拼接sql语句 # 操作 pass def modify(self): # 连接数据库 # 拼接sql语句 # 操作 pass class Handler(object): def index(self): obj = DbHelper.singleton() print id(single) obj.create() return ‘index‘ def news(self): return ‘news‘ def RunServer(environ, start_response): start_response(‘200 OK‘, [(‘Content-Type‘, ‘text/html‘)]) url = environ[‘PATH_INFO‘] temp = url.split(‘/‘)[1] obj = Handler() is_exist = hasattr(obj, temp) if is_exist: func = getattr(obj, temp) ret = func() return ret else: return ‘404 not found‘ if __name__ == ‘__main__‘: httpd = make_server(‘‘, 8001, RunServer) print "Serving HTTP on port 8001..." httpd.serve_forever()
http://www.cnblogs.com/wupeiqi/articles/5017742.html
原文:https://www.cnblogs.com/loser1949/p/9251953.html