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
View Code

 

创建方法

 

构造方法,__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()
View Code

 

面向对象三大特性

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)
    
View Code

 


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')
View Code

 

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()
View Code

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'>)
View Code

在子类中调用父类的方法

 

 

 

 

 

 

 内置方法

 

 

 

 

 

 

 

 

 

 

 

 元类(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)
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('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__()方法,获取返回
        
View Code

 

断言

 

 

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('404')
网页的导航栏,选择不同标题返回不同界面
当反射对象中的方法时,注意返回的是对象方法的地址,外面用一个变量接收后,再变量.()执行才会执行对象中的方法
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

实际运用

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

 

posted @ 2018-05-19 16:08  元贞  阅读(240)  评论(0编辑  收藏  举报