类的创建
class 类名: pass class Bar: def foo(self,arg): # self ,是传的实例对象, print('self:',self,arg) #因为类属性和方法会分别绑定和返回给实例对象 z1 = Bar() print('实例对象:',z1) z1.foo(111) print('================') z2 = Bar() print(z2) z2.foo(666) output>>> 实例对象: <__main__.Bar object at 0x000001DAF653CB70> self: <__main__.Bar object at 0x000001DAF653CB70> 111 ================ <__main__.Bar object at 0x000001DAF653CBE0> self: <__main__.Bar object at 0x000001DAF653CBE0> 666
创建方法
构造方法,__init__(self, arg) obj = 类('a1') 普通方法 obj = 类(‘xxx’) obj.普通方法名() class Person: def __init__(self, name,age): #构造方法,构造方法的特性, 类名() 自动执行构造方法 self.n = name self.a = age self.x = '0' def show(self): print('%s-%s' %(self.n, self.a)) stu1 = Person('kevin', 18) stu1.show() stu2 = Person('lemi', 73) stu2.show()
面向对象三大特性
1.封装
class Bar: def __init__(self, n,a): #通过构造方法封装属性 self.name = n self.age = a self.xue = 'o' b1 = Bar('alex', 123) b2 = Bar('eric', 456)
1.1适用场景
#给对象封装一些值 如果多个函数中有一些相同参数时,转换成面向对象
class DataBaseHelper: def __init__(self, ip, port, username, pwd): self.ip = ip self.port = port self.username = username self.pwd = pwd def add(self,content): # 利用self中封装的用户名、密码等 链接数据 print('content') # 关闭数据链接 def delete(self,content): # 利用self中封装的用户名、密码等 链接数据 print('content') # 关闭数据链接 def update(self,content): # 利用self中封装的用户名、密码等 链接数据 print('content') # 关闭数据链接 def get(self,content): # 利用self中封装的用户名、密码等 链接数据 print('content') # 关闭数据链接 s1 = DataBaseHelper('1.1.1.1',3306, 'alex', 'sb')
2.继承
1、继承 class 父类: pass class 子类(父类): pass 2、重写 防止执行父类中的方法 3、self永远是执行改方法的调用者 4、 super(子类, self).父类中的方法(...) 父类名.父类中的方法(self,...) 5、Python中支持多继承 a. 左侧优先 b. 一条道走到黑 c. 同一个根时,根最后执行
class F: def f1(self): print('F.f1') def f2(self): print('F.f2') class S(F): def s1(self): print('S.s1') def f2(self): # obj print('S.f2') # super(S, self).f2() # 执行父类(基类)中的f2方法 # F.f2(self) # 执行父类(基类)中的f2方法 """ """ obj = S() obj.s1() obj.f2() """ """ obj = S() obj.s1() # s1中的self是形参,此时代指 obj obj.f1() # self用于指调用方法的调用者 """ # obj = S() # obj.f2() """ class Base: def a(self): print('Base.a') class F0(Base): def a1(self): print('F0.a') class F1(F0): def a1(self): print('F1.a') class F2(Base): def a1(self): print('F2.a') class S(F1,F2): pass obj = S() obj.a()
class A(object): def test(self): print('from A') class B(A): def test(self): print('from B') class C(A): def test(self): print('from C') class D(B): def test(self): print('from D') class E(C): def test(self): print('from E') class F(D,E): # def test(self): # print('from F') pass f1=F() f1.test() print(F.__mro__) output>>> from D (<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
在子类中调用父类的方法
内置方法
元类(metaclass)
在Python中一切都是对象,类也是对象,是元类的对象,元类就是类的模板。
在我们平时创建类时,并不是那么简单,会默认执行元类的__init__等几步
---- 图片来自银角大王
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) # 第一阶段:解释器从上到下执行代码创建Foo类 # 第二阶段:通过Foo类创建obj对象 obj = Foo('kevin') print(obj.name)
异常处理
异常就是程序运行时发生错误的信号(在程序出现错误时,则会产生一个异常,若程序没有处理它,则会抛出该异常,程序的运行也随之终止)
--- while True: try: # 代码块,逻辑 inp = input('请输入序号:') i = int(inp) except Exception as e: # e是Exception对象,对象中封装了错误信息 # 上述代码块如果出错,自动执行当前块的内容 print(e) i = 1 print(i) ---异常的捕捉--- def fun(): ret = 0 try: li = [11, 22] #一旦有错误,就会捕捉,下面的错误就不执行,不会出来 li[81] int('w3r') except IndexError as e: #逐级细分错误分类捕捉 print('IndexError',e) #将子异常放在前面,如果Exception在这就包含了所有异常,后面细分就没用了 except ValueError as e: print('ValueError',e) except Exception as e: print('Exception',e) else: #前面错误没有捕捉到才会执行这句,因为有的话前面捕捉到就结束啦。可以原来检测前面的捕捉有没有执行。和while-else 是 while 条件不成立才执行else语句 ret = 1 print('没有错误。。') finally: #最后都要执行这句 print('....') return ret r = fun() if r == 0: print('500') else: pass ---主动抛异常--- try: # 主动出发异常 raise Exception('不过了...') except Exception as e: print(e) --运用 def db(): # return True return False def index(): try: result = db() if not result: r = open('log','a') #当数据库返回有错误时,想要写日志,就想要打开文件写,若果主动抛出异常,就可以在下面一起写 r.write('数据库处理错误') # 打开文件,写日志 #raise Exception('数据库处理错误') #抛出错误给下面捕捉,写日志就写一个啦 except Exception as e: str_error = str(e) print(str_error) r = open('log', 'a') r.write(str_error) # 打开文件,写日志 index() ----------自定义异常--------- class OldBoyError(Exception): def __init__(self, msg): self.message = msg def __str__(self): return self.message # obj = OldBoyError('xxx') # print(obj) try: raise OldBoyError('我错了...') except OldBoyError as e: print(e)# e对象的__str__()方法,获取返回
断言
assert 条件,断言,用于强制用户服从,不服从就报错,可捕获,一般不捕获
print(23) assert 1==2 #不成立,直接报错,不会执行下面的语句 print(456)
总结try..except
- 把错误处理和真正的工作分开来
- 代码更易组织,更清晰,复杂的工作任务更容易实现;
- 毫无疑问,更安全了,不至于由于一些小的疏忽而使程序意外崩溃了;
反射
通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)
class Foo: def __init__(self, name,age): self.name = name self.age = age def show(self): return "%s-%s " %(self.name,self.age) def __int__(self): return 123 def __str__(self): return 'uuu' obj = Foo('alex', 18) r = int(obj) # r = 123 u = str(obj) 我们知道,可以用obj.name去访问对象的属性name,当b = 'name',obj.b时会报错,不能这样 那能不能用字符串也能访问里面的属性或方法 这就要用到反射了 func = getattr(obj, 'show') print(func) r = func() print(r) output>>> <bound method Foo.show of <__main__.Foo object at 0x000001FA6205CC88>> alex-18 #是否有某个属性 print(hasattr(obj, 'name')) #设置 setattr(obj, 'k1', 'v1') print(obj.k1) # v1 #删除 delattr(obj, 'name') # obj.name #已经没有name属性 #运用:去什么东西里面获取什么内容 #获取输入,然后返回值 inp = input('>>>') v = getattr(obj, inp) print(v) Python中一切都是对象,当然也可以对模块进行反射操作 import s2 # r1 = s2.NAME # print(r1) # r2 = s2.func() # print(r2) r1 = getattr(s2, 'NAME') print(r1) r2 = getattr(s2, 'func') result = r2() print(result) cls = getattr(s2, 'Foo') print(cls) obj = cls() print(obj) print(obj.name) --运用-- import s2 inp = input('请输入要查看的URL:') if hasattr(s2, inp): func = getattr(s2, inp) result = func() print(result) else: print('404') 网页的导航栏,选择不同标题返回不同界面 当反射对象中的方法时,注意返回的是对象方法的地址,外面用一个变量接收后,再变量.()执行才会执行对象中的方法
单例模式
单例,用于使用同一份实例(对象)
class Foo: def __init__(self, name,age): self.name = name self.age = age obj = Foo() # obj是Foo的对象,obj也可以叫做Foo类的 实例(实例化) obj1 = Foo() obj2 = Foo() obj3 = Foo() 平时我们创建对象,都是 对象名=类() 这里每个obj对象都是独立的内存地址,然而在某些运用环境下需要使用同一个对象 能不能创建一个实例后,接下来的实例都用同一份实例(或对象),当然可以啦,就是下面的单例模式 class Foo: def __init__(self, name,age): self.name = name self.age = age def show(self): print(self.name,self.age) v = None while True: if v: v.show() else: v = Foo('alex', 123) v.show() 刚开始v是None,进入while 循环会创建一个实例,后面调用v实例就不用创建了,直接调用他的方法 高级一点的表现 class Foo: __v = None @classmethod def get_instance(cls): if cls.__v: return cls.__v else: cls.__v = Foo() return cls.__v # 既然都用单例模式了,就不要在使用 类()去创建实例 #在Foo内部用,get_instance 类方法创建一个实例,后面调用都是返回的同一个,看看输出就知道(都是同一个内存地址) obj1 = Foo.get_instance() print(obj1) obj2 = Foo.get_instance() print(obj2) obj3 = Foo.get_instance() print(obj3) >>>output <__main__.Foo object at 0x0000016C3FB4C4A8> <__main__.Foo object at 0x0000016C3FB4C4A8> <__main__.Foo object at 0x0000016C3FB4C4A8>
实际运用
当用户操作数据库操作数据库连接池时,连接池的接口数量是一定的,用户连接只能共用创建好的连接,不能再创建,当连接都被占用,只有等释放后,供下一个用户连接