python 基础 day8

pickle.load:切记,如果写入文件的是类,一定要先导入相关的类

一、上节回顾补充

二、面向对象(下) 成员

  1、字段 2、方法 3、属性

三、成员修饰符

四、特殊成员

五、面向对象边缘

六、异常处理

七、设计模式之单例模式

一、上节回顾补充

  面向对象基本知识:

    1、类和对象的关系

    2、三大特性: 封装、继承、多态(多种形态、多种类型)

多态

def func(arg):        #python中不用指定参数arg类型
    print(arg)
func(1)               #可以三数字
func("alex")          #可以三字符串
func([11,22,33,])     #可以三列表

在C#/java中 必须制定参数类型,下面用python的方式举例:

def func(A arg): #必须指定类型 
    print(arg)
                
func(123)
func("alex") #报错(如果不是int类型就报错)
            
class A:
    pass
class B(A):
    pass
class C(A):
    pass
#arg 参数:必须是A类型或A的派生类类型
def func(A arg): #这里必须指定父类A,但arg的类型的类型可以三A、B、C
    print(arg)

二、面向对象中 成员

字段:

  静态字段、普通字段

ps:静态字段在代码加载时已经创建

class foo:
    #字段(静态字段)属于类,用类调用
    cc = 123

    def __init__(self):
        #字段(普通的字段)保存在对象里,用对象调用
        self.name = 'alex'  #如果没有创建对象,那么内存里就没有普通字段

一般情况:自己访问自己的字段

class Province:
    country = "中国"

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

hn = Province("河南")
hb = Province("河北")
print(hn.name)  # 在对象里用对象访问
print(Province.country)  # 在类里用类访问
# 在Python里也可以用对象访问静态字段
print(hn.country)

规则:
    普通字段只能用对象访问
    静态字段用类访问(万不得已不要用对象访问)

方法: 所有方法属于类(在其他语言里只有两种方法

1、普通方法:至少一个self,对象执行

2、静态方法:任意参数,没有self,类执行

3、类方法:至少有一个cls参数,由类执行

class Province:
    country = "中国"

    def __init__(self,name):
        self.name = name
    #普通方法,由对象去调用执行(方法属于类)
    def show(self):
        print(self.name)

    #静态方法,由类调用执行(操作1、2、之后变成静态方法)
    @staticmethod #2、加上@staticmethod
    def f1(): #1、参数里去掉self,可以有其他参数
        print("....")

    #类方法(静态方法的一种)
    @classmethod
    def f2(cls): #至少必须有一个参数cls,自动传递参数返回类名
        #cls #类名,()创建对象
        #cls()
        print(cls) #类名<class '__main__.Province'>

    def f3(self):
        return self.name[1]

obj = Province("河南")
obj.show()
Province.f1()
Province.f2()  #<class '__main__.Province'>
ret = obj.f3()
print(ret)     #南 

属性

  不伦不类的东西

  具有方法的写作形式,具有字段的访问形式

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

    @property   #属性就需要加上property这个方法
    def all_pager(self):
        a1,a2 = divmod(self.all_count,10)
        if a2 == 0:
            return  a1
        else:
            return a1 + 1

    @all_pager.setter  #函数名.setter ,设置
    def all_pager(self,value):      #函数名都和上一个相同
        print(value)

    @all_pager.deleter  # 删除
    def all_pager(self):
        print("del")

#all_pager没有加上属性之前,用下面形式操作
#p = Page(101)
# r = p.all_count #字段
# result = p.all_pager() #方法
# print(result)

#all_pager加上属性之后
p.all_count = 102
del p.all_count  #删除方法的字段
ret = p.all_pager #属性 (属性和方法区别就是少了括号)
print(ret)

p.all_pager = 111 #用属性重新定义
del p.all_pager  #用属性删除,伪删除动作,里面执行什么自己定义的

 另一种属性

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

    def f1(self):
        return "f1"

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

    def f3(self):
        print("f3")

    foo = property(fget=f1,fset=f2,fdel=f3) #还可以按顺序直接给值

p = Pager(101)
ret = p.foo
print(ret)

obj = Pager(110)
obj.foo = "f2"

del obj.foo

#结果
f1
f2
f3

三、成员修饰符

  私有的: 只能类自己本身的成员访问调用,其他类不能访问

  公有的: pass

class Foo:
    def __init__(self,name,age):
        self.__name = name #加两个下划线,只能在类的内部访问,外部访问不到
        self.age = age

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

class Bar(Foo):
    def f2(self):
        print(self.age)  #这里如果写成self.__name则外面获取obj1.f2()会报错

obj = Foo("alex",13)
#print(obj.__name)  #会报错,外部不能访问

obj1 = Bar("Q",12)
obj1.f2()   #继承也不能执行__name,只能本身类内部访问
obj1.f1()
#print(obj._Foo__name) #(可以取到私有的,不到万不得已不要强制访问)

四、特殊成员

构造方法 __init__
析构方法 __del__  :垃圾清除之前自动执行 类的__del__方法(有就执行没有不执行)

 __call__ :对象加括号,就会自动执行__call__方法

__str__:直接打印对象,就会自动执行__str__方法

__getitem__:获取

__setitem__:设置

__delitem__:删除

class F:
    #构造方法
    def __init__(self,name,age):
        self.name =name
        self.age =age
    #析构方法
    def __del__(self):
        pass

    def __call__(self, *args, **kwargs):
        print("123")


    def __str__(self):
        return "%s" % self.name

    def __getitem__(self, item):
        # print(item.start)#obj[1:2] 中的1
        # print(item.stop)#2
        # print(item.step) #步长
        return "getitem"

    def __setitem__(self, key, value):
        #key.star key.stop key.step
        return "setitem"

    def __delitem__(self, key):
        # key.star key.stop key.step
        print("del item")
p = F("QL",12)
print(p.__class__) #<class '__main__.F'>

obj = F("QL",15)
#语法对应关系
ret = obj["ad"] # 自动执行getitem方法,自动赋值给item
ret1 = obj[1:2] #切片 会执行getitem方法
print(ret1)
obj[1:4] = [11,22,33,44,55,66,] #自动执行setitem方法
del obj[1:3] #自动执行 delitem
print(obj) #直接打印对象,就会自动执行__str__方法
obj()   #对象加括号,就会自动执行__call__方法
# #ret = obj["k1"] = 111 #自动执行setitem方法
# #print(ret)
#
# del obj["k1"]  #自动执行delitem方法



obj() #加上__call__方法才能执行(对象后加括号)

#F()() #也可以写成这样

print(obj) #不加str会输出内存地址<__main__.F object at 0x0000000000726630>,加上__str__会友好显示,str里返回什么就输出什么

#__dict__ #获取对象中封装的数据 【重要】
ret = obj.__dict__
print(ret) #{'age': 12, 'name': 'QL'}

#print(F.__dict__)#获取类中的成员

 __iter__

class F1():
    def __iter__(self): #iter是生成器(里面有yield就是生成器)
        #yield 1
        #yield 2
        return iter([11, 22, 33, ])

obj = F1()
for item in obj:#默认不可以迭代,加上iter方法才可以迭代
    print(item)#默认执行iter方法,迭代iter返回值

五、面向对象边缘

  - insinstance 查看某个对象是不是某个类创建的

  - issubclass 查看某个类是不是某个类的子类

class A:
    pass

class B(A):
    pass

obj = A()
ret = isinstance(obj,B)

class Bar:
    pass

class Foo(Bar):
    pass

obj = Foo()
#obj,Bar(obj类型和obj类型的父类)的实例
ret2 = isinstance(obj,Bar) #查看obj是不是Bar创建的
print(ret2) #True
ret1 = issubclass(Bar,Foo)# 查看Bar 是不是Foo的子类
print(ret1) #False

 主动执行父类方法:

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) #不建议使用,用上面的super方法

obj1 = C2()
obj1.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) #继承父类的setter
#结果
{'k1': 123, 'k2': 456}

 六、异常处理

while True:
    num1 = input('num1:')
    num2 = input('num2:')
    try:
        li = [11, 22]
        print('li[100]') #indexerro
        num1 = int(num1)
        num2 = int(num2)
        result = num1 + num2


    except ValueError as ex:  #只捕获ValueError错误 从上往下捕获
        print('ex')
    except IndexError as ex:
        print('ex')
    except Exception as ex:  # ex 是Exception的一个对象,Exception捕获所有错误
        print('ex')  # str

 完整代码块

try:
    pass
except ValueError as ex:
    print(ex)
except Exception as ex:
    print(ex)
else:  #上面不报错执行else
    pass
finally: #不管报不报错都执行finally
    pass

 主动触发异常

try:
    raise Exception('主动错误一下') #self.message = '主动错误一下’
    print(1234)
except ValueError as ex:
    print(ex)
except Exception as ex:#__str__,return self.message
    print(ex)
else:  #上面不报错执行else
    pass
finally: #不管报不报错都执行finally
    pass

 断言

assert 1==1 #如果条件成立不报错

assert 1==2 #如果条件不成立报错

p = obj()
p.start() #在执行start之前先执行一个 p.status == False,就可以在start中写入(assert p.staus == False)

七、设计模式之单例模式(23种,推荐书《goF设计模式》)

  单例模式: 用来创建单个实例

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 #对象赋值给instance
            return obj
obj1 = Foo.get_instance()
print(obj1)
obj2 = Foo.get_instance()
print(obj2)

 

谁来访问都创建一个,比较浪费,不如只创建一个,都来访问这一个。

 

原文地址:https://www.cnblogs.com/QL8533/p/5620638.html