• 面向对象进阶


    成员:

    类的成员可以分为三大类:字段、方法和属性

    注:所有成员中,只有普通字段的内容保存对象中,即:根据此类创建了多少对象,在内存中就有多少个普通字段。而其他的成员,则都是保存在类中,即:无论对象的多少,在内存中只创建一份。

    一、字段

    字段包括:普通字段和静态字段,他们在定义和使用中有所区别,而最本质的区别是内存中保存的位置不同,

    • 普通字段属于对象
    • 静态字段属于
    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装饰器

    静态字段方式,创建值为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
    View Code

    成员修饰符:

    有两种,公有成员,私有成员

    • 公有成员,在任何地方都能访问
    • 私有成员,只有在类的内部才能方法
    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()   #派生类不能访问
    私有普通字段daunting

    注:非要访问私有属性的话,可以通过 对象._类__属性名

    面向对象中一些常用特殊方法 :

    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('索引错误')
    执行结果:
    请输入:
    索引错误
    IndexError 索引错误
    inp = input('请输入:')
    try:
        xxx = int(inp)
        print(xxx)
    except ValueError as e:
        print('值错误')
    ValueError 值错误
    dic = {'k1':'213'}
    try:
        dic['k20']
    except KeyError as e:
        print('取值错误')
    执行结果:
    取值错误
    Keyerror 取值错误

    主动触发异常:

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

    面向对象场景二:

    如:创建对数据库操作的公共类

    # #### 定义类 ####
    
    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()
    View Code

    场景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()
    View Code
  • 相关阅读:
    完全用GNU/Linux工作,摈弃Windows你我共勉
    vi编辑器的学习使用(七)
    vi编辑器的学习使用(三)
    Debian 的安装方法
    vi编辑器的学习使用(九)
    vi编辑器的学习使用(六)
    vi编辑器的学习使用(五)
    非常好的javascript:add event/ remove event
    【leetcode】NQueens
    Delphi VCL 的消息处理机制(1)
  • 原文地址:https://www.cnblogs.com/guokaixin/p/5554523.html
Copyright © 2020-2023  润新知