成员:
类的成员可以分为三大类:字段、方法和属性
注:所有成员中,只有普通字段的内容保存对象中,即:根据此类创建了多少对象,在内存中就有多少个普通字段。而其他的成员,则都是保存在类中,即:无论对象的多少,在内存中只创建一份。
一、字段
字段包括:普通字段和静态字段,他们在定义和使用中有所区别,而最本质的区别是内存中保存的位置不同,
- 普通字段属于对象
- 静态字段属于类
class Foo: def __init__(self,name): #普通字段 保存在对象中 self.name = name #普通方法 保存在类中 def shou(self): print('sssssssss') f1 = Foo('开始') print(f1.name) f1.shou() 执行结果 开始 sssssssss
class provice: country = '中国' def __init__(self,name): self.name = name def shou(self): self.name = self.name print(provice.country) shanxi = provice('山西') 执行结果: 中国 山西
静态字段:自己的成员自己访问,除了类中的方法 类中的方法不不要让类访问
由上述代码可以看出【普通字段需要通过对象来访问】【静态字段通过类访问】,在使用上可以看出普通字段和静态字段的归属是不同的 其在内容的存储方式类似如下图:
由上图可是:
- 静态字段在内存中只保存一份
- 普通字段在每个对象中都要保存一份
应用场景: 通过类创建对象时,如果每个对象都具有相同的字段,那么就使用静态字段
方法:
方法包括:普通方法,静态方法,和类方法,三种方法都在内存总归属于类,区别在于调用的方式不同
普通方法: class TXX: def __init__(self,name): self.name = name def fang(self): #定义普通方法,至少要有一个self擦数 print('普通方法sss') tt = TXX(1) tt.fang() 类方法: class Txx: # 类方法 通过class 将类名传进去 def __init__(self,name): self.name = name @classmethod def XXoo(cls): 定义类方法的时候,至少要有一个cls 参数 print('xxxxxxx',cls) Txx.XXoo() class Txx: def __init__(self,name): self.name = name @staticmethod #静态方法 def xoo(): 定义静态方法,无默认的参数 print('静态方法ssssss') Txx.xoo()
相同点:对于所有的方法而言,均属于类(非对象)中,所以,在内存中也只保存一份。
不同点:方法调用者不同、调用方法时自动传入的参数不同。
特性属性:
1.普通特性:为了把方法伪装成字段的形式来访问
a.@property将类中原来的方法伪装成字段的方法去获取
b.@end.setter设置对应特性方法的值
c.在使用特性后的方法不可以添加参数了
class Foo: def __init__(self,name): self.name = name #特性,讲方法伪造成一种字段 @property #获取特性 def end(self): temp = "%s sb"%self.name return temp @end.setter # 设置特性 def end(self,val): print(val) self.name = val obj = Foo('sssss') print(obj.end) obj.end = 'zzzz' print(obj.end)
4, 对于成员的访问与调用:
通过对象访问的 有两种 普通字段,类的方法
通过类访问的 静态字段,静态方法
对于有self参数的就是类调用
没有self参数的就是对象调用
特性的两种方式定义:
属性的定义有两种方式:
- 装饰器 即:在方法上应用装饰器
- 静态字段 即:在类中定义值为property对象的静态字段段
装饰器方式:
在类的普通方法上应用@property装饰器
经典类,具有一种@property装饰器
#!/usr/bin/env/python # -*- coding:utf-8 -*- class FOO: def func(self): print('aaaa') @property def pp(self): print('方法一') return 1111 obj = FOO() obj.func() ret = obj.pp 自动执行 @property 修饰的pp方法 并获取回返回值 print(ret)
class Fooo: def func(self): print('鼠疫') @property def pp(self): print('方法一') return 1111 @pp.setter def pp(self,value): print(value) @pp.deleter def pp(self): print('del') obj = Fooo() obj.func() print(obj.pp) 自动执行 @property 修饰的 pp方法,并获取方法的返回值 obj.pp = 999 自动执行 @price.setter 修饰的 pp 方法,并将 999赋值给方法的参数 del obj.pp # 自动执行 @price.deleter 修饰的 pp方法
静态字段方式,创建值为property对象的静态字段
当使用静态字段的方式创建属性时,经典类和新式类无区别
class FOO: def get(self): return '1111' ss = property(get) obj = FOO() s = obj.ss print(s)
property的构造方法中有个四个参数
- 第一个参数是方法名,调用
对象.属性
时自动触发执行方法 - 第二个参数是方法名,调用
对象.属性 = XXX
时自动触发执行方法 - 第三个参数是方法名,调用
del 对象.属性
时自动触发执行方法 - 第四个参数是字符串,调用
对象.属性.__doc__
,此参数是该属性的描述信息
class FOO: def f1(self): return 'f1111' def f2(self,value): print(value) def f3(self): print('daya') XO = property(fget=f1,fset=f2,fdel=f3,doc='我是说明文档') obj = FOO() ret = obj.XO print(ret) obj.XO = 1234567 del obj.XO
成员修饰符:
有两种,公有成员,私有成员
- 公有成员,在任何地方都能访问
- 私有成员,只有在类的内部才能方法
class C: def __init__(self): self.name = '公有字段' self.__foo = "私有字段
class Foo: xo = 'XO' #公有的静态字段 __ox = 'ox' #私有的静态字段 只能内部访问。 def __init__(self): pass def fetch(self): print(Foo.__ox) self.__aaa = 'xxx' return self.__aaa #私有的普通字段,只能内部访问 print(Foo.xo) #执行公有的静态字段 # print(Foo.__ox) 在外部不能访问 obj = Foo() obj.fetch() print(obj.fetch())
class Too: xxx = '静态字段' def func(self): print(Too.xxx) class Foo(Too): def shou(self): print(Too.xxx) obj = Too() #类内部访问 obj.func() obj1 = Foo() #派生类访问 obj1.shou()
class Too: __xxx = '静态字段' def func(self): print(Too.__xxx) class Foo(Too): def shou(self): print(Too.__xxx) obj = Too() #类内部访问 obj.func() obj1 = Foo() #派生不能类访问 obj1.shou()
- 公有普通字段:对象可以访问;类内部可以访问;派生类中可以访问
- 私有普通字段:仅类内部可以访问;
注:如果想要强制访问私有字段,可以通过 【对象._类名__私有字段明 】访问(如:obj._C__foo),不建议强制访问私有成员。
class Too: def __init__(self): self.name = "公有字段" def func(self): print(self.name) # 类内部访问 class Foo(Too): def shou(self): print(self.name) #派生类中访问 obj = Too() obj.name #通过对象访问 obj.func() #类内部访问 obj1 = Foo() obj1.shou() #派生类中访问
class Too: def __init__(self): self.__name = "私有字段" def func(self): print(self.__name) # 类内部访问 class Foo(Too): def shou(self): print(self.__name) #派生类中不能访问 obj = Too() # obj.__name #对象不能访问 obj.func() #只能类内部可以访问 obj1 = Foo() obj1.shou() #派生类不能访问
注:非要访问私有属性的话,可以通过 对象._类__属性名
面向对象中一些常用特殊方法 :
1,__init__ 构造方法。通过创建对象时,自动触发执行
class Foo: def __init__(self): print('insssssss') obj = Foo() 自动执行类中__init__方法
执行结果:
insssssss
2,__call__ 对象后面加括号,触发执行。
注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()
class Foo: def __call__(self, *args, **kwargs): print('caaaaaaaaa') return 1111111 obj = Foo() obj() #对象后面加括号,触发执行。 ob = Foo()() print(ob)
执行结果:
caaaaaaaaa
caaaaaaaaa
1111111
3,__getitem__、__setitem__、__delitem__用于索引操作,如字典。以上分别表示获取、设置、删除数据
class Foo: def __getitem__(self, item): #用于索引获取数据 print(item) def __setitem__(self, key, value): #设置数据 print(key,value) def __delitem__(self, key): # 删除数据 print(key) obj = Foo() obj['k1'] = 11122223333 del obj['k1']
执行结果:
k1
k1 11122223333
k1
class Foo: def __getitem__(self, item): #用于索引获取数据 print(item,type(item),'__getitem__') def __setitem__(self, key, value): #设置数据 print(key,value,'__setitem__') def __delitem__(self, key): # 删除数据 print(key,'__delitem') obj = Foo() obj[1:3] obj[1:3] = [11,22,33] del obj[1:3]
执行结果:
slice(1, 3, None) <class 'slice'> __getitem__
slice(1, 3, None) [11, 22, 33] __setitem__
slice(1, 3, None) __delitem
4,如果一个类中定义了__str__方法,那么在打印 对象 时,默认输出该方法的返回值。
class Tpp: def __str__(self): return '返回之' ccc = Tpp() print(ccc)
执行结果:
返回之
class Foo: def __init__(self,arg): self.xo = arg def __str__(self): return self.xo obj = Foo('整差皮了...') print(obj)
5,__dict__ 获取类 对象的所有的成员
class Tpp: def __init__(self,name): self.name = name def fff(self): print('xxxxxxxxx') ccc = Tpp('kaishi') print(ccc.name) #获取内容 print(ccc.__dict__) #获取对象的成员 ccc.fff() 执行结果: kaishi {'name': 'kaishi'} xxxxxxxxx
class Tpp: country = 'linshi' def __init__(self,name,country): self.name = name self.country = country def fff(self): print('xxxxxxxxx') ccc = Tpp('kaishi',1111) print(ccc.__dict__) 执行结果: {'country': 1111, 'name': 'kaishi'}
6. __iter__
用于迭代器,之所以列表、字典、元组可以进行for循环,是因为类型内部定义了 __iter__
class Foo: __metaclass__ = 'xxx' def __iter__(self): yield 1 yield 2 yield 3 obj = Foo() # 如果执行for对象时,自动会执行对象的iter方法,生成器 for i in obj: print(i)
异常处理:
异常即是一个事件,该事件会在程序执行过程中发生,影响了程序的正常执行。一般情况下,
在Python无法正常处理程序时就会发生一个异常。
异常是Python对象,表示一个错误。
当Python脚本发生异常时我们需要捕获处理它,否则程序会终止执行。
python中的异常种类非常多,每个异常专门用于处理某一项异常!!!
AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x IOError 输入/输出异常;基本上是无法打开文件 ImportError 无法引入模块或包;基本上是路径问题或名称错误 IndentationError 语法错误(的子类) ;代码没有正确对齐 IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5] KeyError 试图访问字典里不存在的键 KeyboardInterrupt Ctrl+C被按下 NameError 使用一个还未被赋予对象的变量 SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了) TypeError 传入对象类型与要求的不符合 UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量, 导致你以为正在访问它 ValueError 传入一个调用者不期望的值,即使值的类型是正确的
比如我们来输出一个int转换,输入数字就可以执行,输入字母出现错误没有捕捉到则会报错
li = [2222] 定义一个列表 inp = input('请输入:') try: xxx = int(inp) print(xxx) li[1111] 索引列表的内容 except IndexError as e: print('索引错误') 执行结果: 请输入: 索引错误
inp = input('请输入:') try: xxx = int(inp) print(xxx) except ValueError as e: print('值错误')
dic = {'k1':'213'} try: dic['k20'] except KeyError as e: print('取值错误') 执行结果: 取值错误
主动触发异常:
try: print('12345678') raise Exception('差皮了...') except Exception as e: #e 封装了错误的信息的对象 print(e)
执行结果:
12345678
差皮了...
自定义触发异常:
class Foo: def __init__(self,arg): self.xo = arg def __str__(self): return self.xo obj = Foo('整差皮了...') print(obj) 执行结果: 整差皮了...
调用自定义异常
try: raise testError() //实例化自定义异常类,后面括号可传入参数 except testError,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
finally
不管try子句是否发生异常都会执行,比如当你在读写文件或者scoket通讯时,不管是否出现异常都应该在结束后关闭文件或者网络套接字,这时就可以把关闭方法放在finally子句中
try: f = open('db','a')
f.write(data)
except Exception,e: print e finally: f.close()
忽略所有的异常处理:
try: xxx = 'sss'except: pass
这是一种比较危险的用法,它会忽略程序的所有异常而继续的让程序执行下去。
异常处理只需要记住一点:当我们知道某段代码可能会导致某种异常,但我们又不希望程序停止,那么我们就可以根据需要添加异常处理。
单例模式
单例,顾名思义单个实例
实例:
面向对象场景一:
单例模式 只有一个实例 所有的实例中封装的内容都相同时,用单例模式 连接池 class ConnectionPool: __instance = None def __init__(self): self.ip = '1.2.1.1' self.port = 3300 self.username = 'kaisshi' self.pwd = '123123' self.liebiao = [1,2,3,4,5,6,7,8,9,10] @staticmethod def get_instance(): #判断如果类中静态字段有值就执行, if ConnectionPool.__instance: return ConnectionPool.__instance #否则就执行类对象 else: # 创建一个对象,并将对象赋值给静态字段 ConnectionPool.__instance = ConnectionPool() return ConnectionPool.__instance obj = ConnectionPool.get_instance() #执行私有方法 print(obj) obj1 = ConnectionPool.get_instance() print(obj)
面向对象场景二:
如:创建对数据库操作的公共类
- 增
- 删
- 改
- 查
# #### 定义类 #### 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()
场景2实现 web应用:
from wsgiref.simple_server import make_server def RunServer(environ, start_response): start_response(status='200 OK', headers=[('Content-Type', 'text/html')]) url = environ['PATH_INFO'] # return "OldBoy jiaogewwwwwwwwwwssssssssssss" if __name__ == '__main__': httpd = make_server('', 8000, RunServer) print("Serving HTTP on port 8000...") httpd.serve_forever() # # from wsgiref.simple_server import make_server class ConnectionPool: __instance = None def __init__(self): self.ip = "1.1.1.1" self.port = 3306 self.pwd = "123123" self.username = 'xxxx' # 去连接 self.conn_list = [1,2,3,4,5,6,7,8,9,10] @staticmethod def get_instance(): if ConnectionPool.__instance: return ConnectionPool.__instance else: # 创建一个对象,并将对象赋值给静态字段 __instance ConnectionPool.__instance = ConnectionPool() return ConnectionPool.__instance def get_connection(self): # 获取连接 import random r = random.randrange(1,11) return r def index(): # p = ConnectionPool() # print(p) p = ConnectionPool.get_instance() conn = p.get_connection() return "iiiiiii" + str(conn) def news(): return 'nnnnnnn' def RunServer(environ, start_response): start_response(status='200 OK', headers=[('Content-Type', 'text/html')]) url = environ['PATH_INFO'] if url.endswith('index'): ret = index() return ret elif url.endswith('news'): ret = news() return ret else: return "404" if __name__ == '__main__': httpd = make_server('', 8008, RunServer) print("Serving HTTP on port 8008...") httpd.serve_forever()