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 '\nWhy 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>

posted @ 2016-06-27 21:57  颠覆自我  阅读(141)  评论(0编辑  收藏  举报