py-opp 类(class)

时间:2023-03-10 00:25:04
py-opp 类(class)

类的创建

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 = ''
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()

py-opp 类(class)

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__等几步

py-opp 类(class)

---- 图片来自银角大王

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)

s2

异常处理

异常就是程序运行时发生错误的信号(在程序出现错误时,则会产生一个异常,若程序没有处理它,则会抛出该异常,程序的运行也随之终止)

---
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('')
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

  1. 把错误处理和真正的工作分开来
  2. 代码更易组织,更清晰,复杂的工作任务更容易实现;
  3. 毫无疑问,更安全了,不至于由于一些小的疏忽而使程序意外崩溃了;

反射

通过字符串的形式操作对象相关的属性。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('')
网页的导航栏,选择不同标题返回不同界面
当反射对象中的方法时,注意返回的是对象方法的地址,外面用一个变量接收后,再变量.()执行才会执行对象中的方法

s2

单例模式

单例,用于使用同一份实例(对象)

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>

s2

实际运用

  当用户操作数据库操作数据库连接池时,连接池的接口数量是一定的,用户连接只能共用创建好的连接,不能再创建,当连接都被占用,只有等释放后,供下一个用户连接

py-opp 类(class)