zoukankan      html  css  js  c++  java
  • python day8

    一、作业
        要点:
            1、封装,对象中嵌套对象
            2、pickle,load:切记,一定要先导入相关的类
           
           
    二、上节内容回顾和补充
    面向对象基本知识:
        1、类和对象的关系
        2、三大特性:
            封装
            继承
            多态
                       
    多态(多种形态、多种类型)
    # 接受任何类型就是多态
    def func(arg):
        print(arg)

    func(11)
    func('alex')
    func([11,12,22,33])
               

    C#/Java

    def func(list arg):
        print(arg)


    func(123)
    func("alex") # 报错

    class A:
       
        pass
       
    class B(A):
        pass
       
    class C(A):
        pass

    # arg参数:必须是A类型或A的子类类型
    def func(A arg):
        print(arg)

    # obj = B()
    # obj = C()
    obj = A()
    func(obj)
               
               

               
    三、面向对象中类成员
        字段:
            静态字段
            普通字段
            PS:静态字段代码加载时候,已经创建
           
        方法
            所有的方法属于类
            1、普通方法:至少一个self,对象执行
            2、静态方法:任意参数,    类执行(对象执行)
            3、类方法  :至少一个cls, 类执行(对象执行)
        属性
            不论不类的东西
            具有方法的写作形式,具有字段访问形式
           
    1. 字段
    class Foo:
        #字段(静态字段)
        CC = 123
        def __init__(self):
            # 普通字段
            self.name = 'alex'
        def show(self):
            print(self.name)
           
    ret = Foo()
    ret.show()

           
    结果
    alex   
       
       
    多个对像共用一份中国   
    class Province:
        coutory = "中国"                  #静态字段,可共用(类和对象共用)
        def __init__(self,name):
            self.name = name              #普通字段
            print(self.name)
    hn = Province('河南')
    hb = Province('河北')
    sd = Province('山东')
    db = Province('黑龙江')
    #print(hn.name)                        #独个调用


    -----结果
    河南
    河北
    山东
    黑龙江

    #普通字段保存在对像里
    #静态字段保存在类里   


    class Province:
        coutory = "中国"                      #共用,静态字段
        def __init__(self,name):
            self.name = name                  #普通字段

    # 一般情况:自己访问自己字段
    # 规则:
    #   普通字段只能使用对像访问
    #   静态字段用类访问(万不得已的时候可以使用对像)
    hn = Province('河南')
    print(hn.name)                              #对象调用普通字段
    print(Province.coutory)                      #类调用静态字段   
    print(hn.coutory)                          #对象调用静态字段,不建议使用
       
       
    ----结果   
    河南
    中国
    中国


       
       
    2. 类的方法
    所有的方法属于类
        1.普通方法:至少一个self,对像执行
        2.静态方法:任意参数,类执行  (也可对象执行,不对万不得已不用)
        3.类方法,必须有cls,是类名,类执行(也可对象执行,不对万不得已不用)

       
    #对像执行类的方法
    class Province:
        country = "中国"
        def __init__(self,name):
            self.name = name
        def show(self):            #定义show方法
            print(self.name)

    obj = Province("河南")
    obj.show()                    #调用类的show方法

    ----方法合用
    #静态方法,由类调用,不用self,不用创建对像
    # @staticmethod  和  @classmethod 使用
    class Province:
        country = '中国'                    #静态字段,共用,静态字段,由类执行
        def __init__(self,name):            #构造方法
            self.name = name                #普通字段,由对象调用
           
        #普通方法,由对象去调用执行(方法属于类)
        def show(self):                     #普通方法
            #print(self.name)
            print(123)

        @staticmethod                       #静态方法
        #def f1(arg1,arg2):
        def f1(cla,arg1,arg2):
            #静态方法,由类调用执行,由类调用执行,不用self
            print(arg1,arg2)

        @classmethod                        #类方法
        def f2(cls):                        #必须要有cls参数,cls全拼就是class,自动传值,就是把类当成参数传递
            print(cls)
           
     
    #Province.f1(11,22)                      #调用静态方法
    Province.f1(Province,11,22)                #调用静态方法
    #Province.f1('fsafdsa',11,22)
    Province.f2()                           #调用类方法


    3. 属性

    #类的属性,不用括号
    class Pager:
        def __init__(self,all_count):
            self.all_count = all_count
        @property                                       #属性
        def all_pager(self):
            a1,a2 = divmod(self.all_count,10)           #除法算余商
            if a2 == 0:                                    #如果没有余数,回显__init__的all_count
                return a1                               

            else:                                        #否则商加1
                return a1 + 1                           
    p = Pager(101)                        #传101,就是100除以10
    ret = p.all_pager                    #不用括号调用执行类方法,即类的属性
    print(ret)

    结果
    11   
       


    类属性的获取,设置,删除功能,只是执行对应的属性调用对应的方法
        # @property     
        # @.setter
        # @.deleter


    class Pager:
        def __init__(self,all_count):
            self.all_count = all_count

        @property                        #获取
        def all_pager(self):
            a1,a2 = divmod(self.all_count,10)
            if a2 == 0:
                return a1
            else:
                return a1 + 1

        @all_pager.setter               #设置
        def all_pager(self,value):
            print(value)

        @all_pager.deleter              #删除
        def all_pager(self):
            print('del all_pager')
           
    p = Pager(101)

    ret = p.all_pager                         #执行这句就调用@property “获取”
    print(ret)
    p.all_pager = 111                         #执行这句就调用@all_pager.setter “设置”
    del p.all_pager                           #执行这句就调用@all_pager.deleter "删除"

    结果
    11
    111
    del all_pager


    类的属性另一种使用方法
    class Pager:
        def __init__(self,all_count):
            self.all_count = all_count

        def f1(self):
            return 123

        def f2(self,value):
            print(value)

        def f3(self):
            print('wmh')

        foo = property(fget=f1,fset=f2,fdel=f3)       #fget获取,fset设置,fdel删除

    p = Pager(101)
    result = p.foo       #调用fget=f1
    print(result)
    p.foo = 'alex'       #调用fset=f2
    del p.foo            #调用fdel=f3

    结果
    123
    alex
    wmh

       
       
    四、成员修饰符
            私有:
                只能类自己本身成员内部可以访问
            公有:
                   
    公有成员,在任何地方都能访问
    私有成员,只有在类的内部才能方法

    私有成员和公有成员的定义不同:私有成员命名时,前两个字符是下划线。(特殊成员除外,例如:__init__、__call__、__dict__等)
    class C:
        def __init__(self):
            self.name = '公有字段'
            self.__foo = "私有字段"


    私有成员和公有成员的访问限制不同:
    静态字段
    公有静态字段:类可以访问;类内部可以访问;派生类中可以访问
    私有静态字段:仅类内部可以访问;
    class C:
        name = '公有静态字段'
        def func(self):
            print(C.name)

    class D(C):
        def show(self):
            print(C.name)

    C.name         # 类访问

    obj = C()
    obj.func()     # 类内部可以访问

    obj_son = D()
    obj_son.show() # 派生类中可以访问

               
                   
                   
    1. 私有
    #字段前面加__即创建私有字段,只有在内部调用
    class Foo:
        def __init__(self,name):
            self.__name = name           #__name 是私有字段,创建私有字段,只有内部可以调用
        def f1(self):
            print(self.__name)          #内部可以访问私有字段

    obj = Foo('alex')
    print(obj.__name)                      # 不能用,这样写就会报错,因为外部访问不了
    obj.f1()                            #可以调用

    静态字段,私有调用
    class Foo:
        __cc = '123'                 #静态字段,私有使用

        def __init__(self,name):
            self.__name = name

        def f1(self):
            print(self.__name)             

        @staticmethod
        def f3():
            print(Foo.__cc)         #可以内部调用

    #print(Foo.__cc)               #调用会报错因为是私有
    obj = Foo('dddd')
    obj.f3()
    Foo.f3()

    结果
    123
    123


    私有字段,外部类也访问不了,即使你继承了它
    class Foo:
        def __init__(self,name):
            self.__name = name           #__name 是私有字段

        def f1(self):
            print(self.__name)           #内部可以访问私有字段

    class Bar(Foo):                      #Bar类继承了Foo类
        def f2(self):
            print(self.__name)           #这里的类调用Foo类的__name是访问不了的,因为私有字段外部调用不了

    obj = Bar("alex")
    #obj.f2()                            #这里Bar类里调用f2方法继承Foo父类的__name是引用不了的,会报错
    obj.f1()                             #这里Bar类直接输出父类的__name是可以的,所以可以打印alex


    结果如下:
    alex


    特殊情况下,外部调用私有字段
    class Foo:
        def __init__(self, name):
            self.__name = name

        def f1(self):
            print(self.__name)
           
    obj = Foo("alex")
    #print(obj.__name)                #直接调用私有字段是不可以的,会报错
    print(obj._Foo__name)           #强制调用私有,语法:_类名__字段名


    结果
    alex

    2. 公有
    # 类内外都能访问的是公有字段,没有__下划线字段是公有字段,有__字段是私有字段
    class Foo:
        def __init__(self,name):
            self.name = name

        def f1(self):
            print(self.name)

    obj = Foo('alex')
    print(obj.name)
    obj.f1()

    五. 特殊成员
        __init__:     构造方法:如果存在,类首先自动执行,__init__() 就是调用构造方法
        __del__:      析构方法:如果存在,类最后会自动执行,__del__() 就是调用析构方法
        __call__:     call方法:就是 对象() 执行call方法
        __str__:      如果一个类中定义了__str__方法,那么打印对象时,默认输出该方法的返回值
        __doc__
        __setitem__

       
       
       
    1. __doc__

    表示类的描述信息
    class Foo:
        """ 描述类信息,这是用于看片的神奇 """

        def func(self):
            pass

    print(Foo.__doc__)
    #输出:类的描述信息

    ----结果
    描述类信息,这是用于看片的神奇


    2. __init__
    构造方法,通过类创建对象时,自动触发执行。

    class Foo:
        def __init__(self,name):
            self.name = name
            self.age = 19
    obj = Foo('wmh')            # 自动执行类中的 __init__ 方法
    print(obj.name)
    print(obj.age)


    4. __del__
    析构方法,当对象在内存中被释放时,自动触发执行。
    注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。

     
    class Foo:
        def __del__(self):
            pass

           
           
    5. __call__

    对象后面加括号,触发执行。
    注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()

    class Foo:
        def __init__(self):
            pass 
        def __call__(self, *args, **kwargs):
            print('__call__')
    obj = Foo() # 执行 __init__
    obj()       # 执行 __call__   
       

    结果
    __call__
       
       
    6. __dict__ 类或对象中的所有成员
    上文中我们知道:类的普通字段属于对象;类中的静态字段和方法等属于类,即:

    #以字典的方式取字段和对像传数值
    class Province:

        country = 'China'

        def __init__(self, name, count):
            self.name = name
            self.count = count

        def func(self, *args, **kwargs):
            print 'func'

    # 获取类的成员,即:静态字段、方法、
    print(Province.__dict__)
    # 输出:{'country': 'China', '__module__': '__main__', 'func': <function func at 0x10be30f50>, '__init__': <function __init__ at 0x10be30ed8>, '__doc__': None}

    obj1 = Province('HeBei',10000)
    print(obj1.__dict__)
    # 获取 对象obj1 的成员
    # 输出:{'count': 10000, 'name': 'HeBei'}

    obj2 = Province('HeNan', 3888)
    print(obj2.__dict__)
    # 获取 对象obj1 的成员
    # 输出:{'count': 3888, 'name': 'HeNan'}

    7. __str__
    如果一个类中定义了__str__方法,那么在打印 对象 时,默认输出该方法的返回值。
    class Foo:

        def __str__(self):
            return 'wupeiqi'
    obj = Foo()
    print(obj)
    # 输出:wupeiqi


    8、__getitem__、__setitem__、__delitem__
    用于索引操作,如字典。以上分别表示获取、设置、删除数据
    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    class Foo(object):
        def __getitem__(self, key):
            print('__getitem__',key)
        def __setitem__(self, key, value):
            print('__setitem__',key,value)
        def __delitem__(self, key):
            print('__delitem__',key)
    obj = Foo()
    result = obj['k1']      # 自动触发执行 __getitem__
    obj['k2'] = 'wmh'       # 自动触发执行 __setitem__
    del obj['k1']           # 自动触发执行 __delitem__


    结果
    __getitem__ k1
    __setitem__ k2 wmh
    __delitem__ k1


    9、__getslice__、__setslice__、__delslice__
    该三个方法用于分片操作,如:列表
    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    class Foo(object):
        def __getslice__(self, i, j):
            print('__getslice__',i,j)
        def __setslice__(self, i, j, sequence):
            print('__setslice__',i,j)
        def __delslice__(self, i, j):
            print('__delslice__',i,j)
    obj = Foo()
    #obj[-1:1]                   # 自动触发执行 __getslice__
    obj[0:1] = [11,22,33,44]    # 自动触发执行 __setslice__
    del obj[0:2]                # 自动触发执行 __delslice__


    10. __iter__
    #加__iter__就是为了给类for 循环
    用于迭代器,之所以列表、字典、元组可以进行for循环,是因为类型内部定义了 __iter__
    class Foo(object):
        pass
    obj = Foo()
    for i in obj:
        print i 
    # 报错:TypeError: 'Foo' object is not iterable


    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    class Foo(object):
        def __iter__(self):
            pass
    obj = Foo()
    for i in obj:
        print i
    # 报错:TypeError: iter() returned non-iterator of type 'NoneType'

    ----加__iter__就是为了给类for 循环递归,一个一个取
    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    class Foo(object):
        def __init__(self, sq):
            self.sq = sq
        def __iter__(self):
            return iter(self.sq)
    obj = Foo([11,22,33,44])
    for i in obj:
        print(i)
       
       
    结果
    11
    22
    33
    44


    以上步骤可以看出,for循环迭代的其实是  iter([11,22,33,44]) ,所以执行流程可以变更为:
    #!/usr/bin/env python
    # -*- coding:utf-8 -*-

    obj = iter([11,22,33,44])
    for i in obj:
        print(i)

       
       

       

    1. call方法
    class Foo:

        #构造方法:如果存在,类首先自动执行,__init__() 就是调用构造方法
        def __init__(self):
            print('__init__')

        #析构方法:如果存在,类最后会自动执行,__del__() 就是调用析构方法
        def __del__(self):
            print('__del__')

        #call方法:可以对象直接加()调用
        def __call__(self):
            print('__call__')
       
    obj = Foo()
    obj()              #对象直接调用call方法
    Foo()()            #与上面完全相同

    2. str方法
    class Foo:

        #构造方法:如果存在,类首先自动执行,__init__() 就是调用构造方法
        def __init__(self,name,age):
            self.name = name
            self.age = age

        #析构方法:如果存在,类最后会自动执行,__del__() 就是调用析构方法
        def __del__(self):
            print('__del__')
           
        #call方法:可以对象直接加()调用
        def __call__(self):
            print('__call__')
       
        #如果一个类中定义了__str__方法,那么打印对象时,默认输出该方法的返回值
        def __str__(self):
            return '%s - %d' %(self.name,self.age)
           
    obj1 = Foo('alex',73)
    obj2 = Foo('eric',84)
    #print(obj1)
    #print(obj2)

    ret = str(obj1)
    print(ret)


    结果
    alex - 73
    __del__
    __del__


    3. dict 方法
    #获取类中的所有字段的数据
    class Foo:

        #构造方法:如果存在,类首先自动执行,__init__() 就是调用构造方法
        def __init__(self,name,age):
            self.name = name
            self.age = age

        #析构方法:如果存在,类在最后会自动执行,__del__() 就是调用析构方法
        def __del__(self):
            print('__del__')
        def __call__(self):
            print('__call__')
       
        #如果一个类中定义了__str__方法,那么打印对象时,默认输出该方法的返回值
        def __str__(self):
            return '%s - %d' %(self.name,self.age)
           
    obj1 = Foo('alex',73)
    obj2 = Foo('eric',84)
    ret = obj1.__dict__                 #获取类中的所有字段的数据
    print(ret)


    class Foo:
        #构造方法:如果存在,类首先自动执行,__init__() 就是调用构造方法
        def __init__(self,name,age):
            self.name = name
            self.age = age
        def __getitem__(self, item):
            return 123
        def __setitem__(self, key, value):
            print('setitem')
        def __delitem__(self, key):
            print('del item')

    obj = Foo('alex',73)
    ret = obj['ad']            #执行__getitem__方法
    print(ret)
    obj['k1'] = 111             #执行__setitem__方法
    del obj['k1']               #执行__delitem__方法


    #取步长
    li = [11,22,33,44,55]
    print(li[0:5:2])            #2为取步长,在0到5的索引范围取两步的值

    #切片类型使用,重要看结果都是切片类型
    class Foo:

        # 构造方法
        def __init__(self, name,age):
            self.name = name
            self.age = age

        # 析构方法
        def __del__(self):
            pass

        def __call__(self):
            print('call')

        def __str__(self):
            return "%s - %d" %(self.name, self.age)

        def __add__(self, other):
            temp = "%s - %d" %(self.name,other.age)
            return temp

        def __getitem__(self, item):
            # print(type(item),item)
            # item.start   item.stop  item.step
            print(type(item))
            return 123

        def __setitem__(self, key, value):
            # key.start   key.stop  key.step
            print(type(key),type(value))

        def __delitem__(self, key):
            # key.start   key.stop  key.step
            print(type(key))


    obj = Foo('alex', 73)
    # obj() # call
    # 语法对应关系
    # ret1 = obj['ad']
    ret2 = obj[1:4:2]
    obj[1:4] = [11,22,33,44,66]
    del obj[1:4]

    结果
    <class 'slice'>
    <class 'slice'> <class 'list'>
    <class 'slice'>

    类的迭代
    #使用__iter__是为了给类for循环迭代
    li = list([11,22,33,44])
    for item in li:
        print(item)


    class Foo:
        def __iter__(self):
            return iter([11,22,33,44])

    obj = Foo()                 #对象迭代
    for item in obj:
        print(item)

    结果
    11
    22
    33
    44


    for 循环对象默认引用iter方法
    #有yield即生成器
    class Foo:
        def __iter__(self):
            yield 1
            yield 2

    obj = Foo()                 #对象迭代
    for item in obj:
        print(item)

    结果
    1
    2


       
    六、面向对象其他
            - isinstance
            - issubclass
            - 继承 2.7
            - 应用:
                自定义类型,对字典进行补充,有序字典
                源码的扩展
               
               
               
    1.     isinstance    和 issubclass
    # isinstance(obj,Bar) 判断一个对像是否是一个对像创建的

    class Bar:
        pass

    class Foo(Bar):
        pass


    obj = Foo()
    #obj,Bar(obj类型和obj类型的父类)的实列
    ret = isinstance(obj,Bar)    #判断obj是否是Bar类创建的
    print(ret)
    ret = issubclass(Bar,Foo)    #判断类是否某类的父类
    print(ret)
                  
               
               
    结果
    True
    False   
      

               
               
           
               
    七、异常处理
    #当程序有异常情况,异常就出现了,就需要异常处理,有默认异常和自创建异常

    while True:
        num1 = input('num1:')
        num2 = input('num2:')
        try:
            num1 = int(num1)
            num2 = int(num2)
            result = num1 + num2
        except Exception as ex:
            print(ex)   #str

    结果
    num1:wrw
    num2:fdsafa
    invalid literal for int() with base 10: 'wefwrw'

    自定义异常
    #raise 引发异常
    #!/usr/bin/python
    # Filename: raising.py
    class Error1(Exception):
            '''A user-defined exception class.'''
            def __init__(self, length, atleast):
                    Exception.__init__(self)
                    self.length = length
                    self.atleast = atleast
    try:
            s = raw_input('Enter something --> ')
            if len(s) < 3:
                    raise Error1(len(s), 3) #raise 引发异常
            # Other work can continue as usual here
    except EOFError:
            print ' Why did you do an EOF on me?'
    except Error1, x:
            print 'Error1: The input was of length%d,was expecting at least %d' % (x.length,x.atleast)
    else:
            print 'No exception was raised.'


    #测试
    python raising.py
    Enter something -->       #输入小于三位即触发Error1
        Error1: The input was of length0,was expecting at least 3   #回显输入长度,至少长度为3

    python raising.py  
    Enter something --> jalksjdlajflksafalds   #输入长度超过3,即调用else的正常,没有异常触发
        No exception was raised.           #没有异常触发

    python raising.py
    Enter something -->        #非法操作ctrl+d即,返回FOFError
        Why did you do an EOF on me?  #你对我做了什么

    #finally 无论异常发生于否都执行操作,总是会运行
    touch poem.txt

    vi finally.py
    import time
    try:
            f = file('poem.txt')
            while True:
                    line=f.readline()
                    if len(line)==0:
                            break
                    time.sleep(2)  # time.sleep 方法暂停2秒钟
                    print line,
    finally:
            f.close()
            print 'Cleaning up.....closed the file'
           
           
           
           
           
           

    八、设计模式之单例模式
       
        类方法
        静态方法
       
    1.类方法   
    执行父类的方法  
    class C1:
        def f1(self):
            print('c1.f1')

    class C2(C1):
        def f1(self):
            #主动执行父类的f1方法
            super(C2,self).f1()
            print('c2.f1')
            #C1.f1(self)  #   python 2.0 执行父类f1方法
    obj = C2()
    obj.f1()


    结果
    c1.f1
    c2.f1
                      
       

       

    #实现有序的字典
    class MyDict(dict):
        def __init__(self):
            self.li = []
            super(MyDict,self).__init__()
        def __setitem__(self, key, value):
            self.li.append(key)
            super(MyDict,self).__setitem__(key,value)
        def __str__(self):
            temp_list = []
            for key in self.li:
                value = self.get(key)
                temp_list.append("'%s':%s" % (key,value,))
            temp_str = "{" + ",".join(temp_list) + "}"                #字符串拼接成的有序字典
            return temp_str

    #
    obj = MyDict()
    obj['k1'] = 123
    obj['k2'] = 456
    print(obj)


    结果
    {'k1':123,'k2':456}

    2. 单例模式
    #永远都是一个结果
    class Foo:

        instance = None

        def __init__(self,name):
            self.name = name

        @classmethod
        def get_instance(cls):
            # cls类名
            if cls.instance:
                return cls.instance
            else:
                obj = cls('alex')
                cls.instance = obj
                return obj

    obj1 = Foo.get_instance()
    print(obj1)
    obj2 = Foo.get_instance()
    print(obj2)


    结果
    <__main__.Foo object at 0x00000000010E3978>
    <__main__.Foo object at 0x00000000010E3978>

  • 相关阅读:
    Git命令与使用
    Android与WebView的JS交互
    Android 中关于硬件加速的使用和问题
    Activity-生命周期和启动模式
    Activity-恢复与保存状态或数据
    Android中Paint的一些使用心得记录
    Java中sleep,wait的区别
    C#基本类型
    LeetCode74 搜索二维矩阵
    leetcode 43 字符串相乘 java
  • 原文地址:https://www.cnblogs.com/wangminghu/p/5621710.html
Copyright © 2011-2022 走看看