奇迹969

 

面向对象

单例模式   继承

基础

https://www.cnblogs.com/Eva-J/articles/7293890.html

进阶

https://www.cnblogs.com/Eva-J/articles/7351812.html

 封装 继承  多态

一、特性property
property是一种特殊的属性,访问它时会执行一段功能(函数)然后返回值

1、什么事特性property

import math
   
class Circle:
    def __init__(self,radius):
        self.radius =radius
 
    @property    方法化属性
    def area(self):
        return math.pi*self.radius**2 #计算圆的面积
 
    @property
    def perimeter(self):
        return 2*math.pi*self.radius  #计算圆的周长
 
c = Circle(5)
print(c.area) #可以向访问数据属性一样去访问area,会触发一个函数的执行,动态计算出一个值
print(c.perimeter)


 

课程:⾯向对象-继承
⽬标
继承的概念
单继承
多继承
⼦类重写⽗类的同名属性和⽅法
⼦类调⽤⽗类的同名属性和⽅法
多层继承
super()
私有属性和私有⽅法
⼀. 继承的概念
⽣活中的继承,⼀般指的是⼦⼥继承⽗辈的财产。
拓展1:经典类或旧式类
不由任意内置类型派⽣出的类,称之为经典类。
拓展2:新式类
class 类名:
 代码
 ......

class 类名(object):
 代码

Python⾯向对象的继承指的是多个类之间的所属关系,即⼦类默认继承⽗类的所有属性和⽅法,具体如
下:
在Python中,所有类默认继承object类,object类是顶级类或基类;其他⼦类叫做派⽣类。
⼆. 单继承
故事主线:⼀个煎饼果⼦⽼师傅,在煎饼果⼦界摸爬滚打多年,研发了⼀套精湛的摊煎饼果⼦的
技术。师⽗要把这套技术传授给他的唯⼀的最得意的徒弟。
分析:徒弟是不是要继承师⽗的所有技术?
# ⽗类A
class A(object):
 def __init__(self):
 self.num = 1
 def info_print(self):
 print(self.num)
# ⼦类B
class B(A):
 pass
result = B()
result.info_print() # 1

# 1. 师⽗类
class Master(object):
 def __init__(self):
 self.kongfu = '[古法煎饼果⼦配⽅]'
 def make_cake(self):
 print(f'运⽤{self.kongfu}制作煎饼果⼦')
 
# 2. 徒弟类
class Prentice(Master):
 pass
# 3. 创建对象daqiu
daqiu = Prentice()
# 4. 对象访问实例属性
print(daqiu.kongfu) 123456789

三. 多继承
故事推进:daqiu是个爱学习的好孩⼦,想学习更多的煎饼果⼦技术,于是,在百度搜索到⿊⻢程
序员,报班学习煎饼果⼦技术。
所谓多继承意思就是⼀个类同时继承了多个⽗类。
注意:当⼀个类有多个⽗类的时候,默认使⽤第⼀个⽗类的同名属性和⽅法。
四. ⼦类重写⽗类同名⽅法和属性
故事:daqiu掌握了师⽗和培训的技术后,⾃⼰潜⼼钻研出⾃⼰的独⻔配⽅的⼀套全新的煎饼果⼦
技术。
# 5. 对象调⽤实例⽅法
daqiu.make_cake()

class Master(object):
 def __init__(self):
 self.kongfu = '[古法煎饼果⼦配⽅]'
 def make_cake(self):
 print(f'运⽤{self.kongfu}制作煎饼果⼦')
# 创建学校类
class School(object):
 def __init__(self):
 self.kongfu = '[⿊⻢煎饼果⼦配⽅]'
 def make_cake(self):
 print(f'运⽤{self.kongfu}制作煎饼果⼦')
class Prentice(School, Master):
 pass
daqiu = Prentice()
print(daqiu.kongfu)
daqiu.make_cake()

class Master(object):
 def __init__(self):

⼦类和⽗类具有同名属性和⽅法,默认使⽤⼦类的同名属性和⽅法。
五. ⼦类调⽤⽗类的同名⽅法和属性
故事:很多顾客都希望也能吃到古法和⿊⻢的技术的煎饼果⼦。
 self.kongfu = '[古法煎饼果⼦配⽅]'
 def make_cake(self):
 print(f'运⽤{self.kongfu}制作煎饼果⼦')
class School(object):
 def __init__(self):
 self.kongfu = '[⿊⻢煎饼果⼦配⽅]'
 def make_cake(self):
 print(f'运⽤{self.kongfu}制作煎饼果⼦')
# 独创配⽅
class Prentice(School, Master):
 def __init__(self):
 self.kongfu = '[独创煎饼果⼦配⽅]'
 def make_cake(self):
 print(f'运⽤{self.kongfu}制作煎饼果⼦')
daqiu = Prentice()
print(daqiu.kongfu)
daqiu.make_cake()
print(Prentice.__mro__) 3456789

class Master(object):
 def __init__(self):
 self.kongfu = '[古法煎饼果⼦配⽅]'
 def make_cake(self):
 print(f'运⽤{self.kongfu}制作煎饼果⼦')
class School(object):
 def __init__(self):
 self.kongfu = '[⿊⻢煎饼果⼦配⽅]'

六. 多层继承
故事:N年后,daqiu⽼了,想要把所有技术传承给⾃⼰的徒弟。
 def make_cake(self):
 print(f'运⽤{self.kongfu}制作煎饼果⼦')
class Prentice(School, Master):
 def __init__(self):
 self.kongfu = '[独创煎饼果⼦配⽅]'
 def make_cake(self):
 # 如果是先调⽤了⽗类的属性和⽅法,⽗类属性会覆盖⼦类属性,故在调⽤属性前,先调⽤
⾃⼰⼦类的初始化
 self.__init__()
 print(f'运⽤{self.kongfu}制作煎饼果⼦')
 # 调⽤⽗类⽅法,但是为保证调⽤到的也是⽗类的属性,必须在调⽤⽅法前调⽤⽗类的初始化
 def make_master_cake(self):
 Master.__init__(self)
 Master.make_cake(self)
 def make_school_cake(self):
 School.__init__(self)
 School.make_cake(self)
daqiu = Prentice()
daqiu.make_cake()
daqiu.make_master_cake()
daqiu.make_school_cake()
daqiu.make_cake()

class Master(object):
 def __init__(self):
 self.kongfu = '[古法煎饼果⼦配⽅]'
 def make_cake(self):
 print(f'运⽤{self.kongfu}制作煎饼果⼦') 1234567
七. super()调⽤⽗类⽅法
class School(object):
 def __init__(self):
 self.kongfu = '[⿊⻢煎饼果⼦配⽅]'
 def make_cake(self):
 print(f'运⽤{self.kongfu}制作煎饼果⼦')
class Prentice(School, Master):
 def __init__(self):
 self.kongfu = '[独创煎饼果⼦配⽅]'
 def make_cake(self):
 self.__init__()
 print(f'运⽤{self.kongfu}制作煎饼果⼦')
 def make_master_cake(self):
 Master.__init__(self)
 Master.make_cake(self)
 def make_school_cake(self):
 School.__init__(self)
 School.make_cake(self)
# 徒孙类
class Tusun(Prentice):
 pass
xiaoqiu = Tusun()
xiaoqiu.make_cake()
xiaoqiu.make_school_cake()
xiaoqiu.make_master_cake()

class Master(object):
 def __init__(self):
 self.kongfu = '[古法煎饼果⼦配⽅]'
1234
 def make_cake(self):
 print(f'运⽤{self.kongfu}制作煎饼果⼦')
class School(Master):
 def __init__(self):
 self.kongfu = '[⿊⻢煎饼果⼦配⽅]'
 def make_cake(self):
 print(f'运⽤{self.kongfu}制作煎饼果⼦')
 # ⽅法2.1
 # super(School, self).__init__()
 # super(School, self).make_cake()
 # ⽅法2.2
 super().__init__()
 super().make_cake()
class Prentice(School):
 def __init__(self):
 self.kongfu = '[独创煎饼果⼦技术]'
 def make_cake(self):
 self.__init__()
 print(f'运⽤{self.kongfu}制作煎饼果⼦')
 # ⼦类调⽤⽗类的同名⽅法和属性:把⽗类的同名属性和⽅法再次封装
 def make_master_cake(self):
 Master.__init__(self)
 Master.make_cake(self)
 def make_school_cake(self):
 School.__init__(self)
 School.make_cake(self)
 # ⼀次性调⽤⽗类的同名属性和⽅法
 def make_old_cake(self):
 # ⽅法⼀:代码冗余;⽗类类名如果变化,这⾥代码需要频繁修改
 # Master.__init__(self)
 # Master.make_cake(self)
 # School.__init__(self)
 # School.make_cake(self)
 # ⽅法⼆: super()
 # ⽅法2.1 super(当前类名, self).函数()
 # super(Prentice, self).__init__()
 # super(Prentice, self).make_cake()

注意:使⽤super() 可以⾃动查找⽗类。调⽤顺序遵循 __mro__ 类属性的顺序。⽐较适合单继承
使⽤。
⼋. 私有权限
8.1 定义私有属性和⽅法
在Python中,可以为实例属性和⽅法设置私有权限,即设置某个实例属性或实例⽅法不继承给⼦类。
故事:daqiu把技术传承给徒弟的同时,不想把⾃⼰的钱(2000000个亿)继承给徒弟,这个时候就
要为 钱 这个实例属性设置私有权限。
设置私有权限的⽅法:在属性名和⽅法名 前⾯ 加上两个下划线 __。
 # ⽅法2.2 super().函数()
 super().__init__()
 super().make_cake()
daqiu = Prentice()
daqiu.make_old_cake()

class Master(object):
 def __init__(self):
 self.kongfu = '[古法煎饼果⼦配⽅]'
 def make_cake(self):
 print(f'运⽤{self.kongfu}制作煎饼果⼦')
class School(object):
 def __init__(self):
 self.kongfu = '[⿊⻢煎饼果⼦配⽅]'
 def make_cake(self):
 print(f'运⽤{self.kongfu}制作煎饼果⼦')
class Prentice(School, Master):
 def __init__(self):
 self.kongfu = '[独创煎饼果⼦配⽅]'
 # 定义私有属性
 self.__money = 2000000

注意:私有属性和私有⽅法只能在类⾥⾯访问和修改。
8.2 获取和修改私有属性值
在Python中,⼀般定义函数名 get_xx ⽤来获取私有属性,定义 set_xx ⽤来修改私有属性值。
 # 定义私有⽅法
 def __info_print(self):
 print(self.kongfu)
 print(self.__money)
 def make_cake(self):
 self.__init__()
 print(f'运⽤{self.kongfu}制作煎饼果⼦')
 def make_master_cake(self):
 Master.__init__(self)
 Master.make_cake(self)
 def make_school_cake(self):
 School.__init__(self)
 School.make_cake(self)
# 徒孙类
class Tusun(Prentice):
 pass
daqiu = Prentice()
# 对象不能访问私有属性和私有⽅法
# print(daqiu.__money)
# daqiu.__info_print()
xiaoqiu = Tusun()
# ⼦类⽆法继承⽗类的私有属性和私有⽅法
# print(xiaoqiu.__money) # ⽆法访问实例属性__money
# xiaoqiu.__info_print()

class Master(object):
 def __init__(self):
 self.kongfu = '[古法煎饼果⼦配⽅]'
 def make_cake(self):
 print(f'运⽤{self.kongfu}制作煎饼果⼦')
class School(object):
123456789
 def __init__(self):
 self.kongfu = '[⿊⻢煎饼果⼦配⽅]'
 def make_cake(self):
 print(f'运⽤{self.kongfu}制作煎饼果⼦')
class Prentice(School, Master):
 def __init__(self):
 self.kongfu = '[独创煎饼果⼦配⽅]'
 self.__money = 2000000
 # 获取私有属性
 def get_money(self):
 return self.__money
 # 修改私有属性
 def set_money(self):
 self.__money = 500
 def __info_print(self):
 print(self.kongfu)
 print(self.__money)
 def make_cake(self):
 self.__init__()
 print(f'运⽤{self.kongfu}制作煎饼果⼦')
 def make_master_cake(self):
 Master.__init__(self)
 Master.make_cake(self)
 def make_school_cake(self):
 School.__init__(self)
 School.make_cake(self)
# 徒孙类
class Tusun(Prentice):
 pass
daqiu = Prentice()
xiaoqiu = Tusun()
# 调⽤get_money函数获取私有属性money的值
print(xiaoqiu.get_money())
# 调⽤set_money函数修改私有属性money的值
xiaoqiu.set_money()

九. 总结
继承的特点
⼦类默认拥有⽗类的所有属性和⽅法
⼦类重写⽗类同名⽅法和属性
⼦类调⽤⽗类同名⽅法和属性
super()⽅法快速调⽤⽗类⽅法
私有权限
不能继承给⼦类的属性和⽅法需要添加私有权限
语法
59 print(xiaoqiu.get_money())
class 类名():
 # 私有属性
 __属性名 =# 私有⽅法
 def __函数名(self):
 代码

 

⼆. 多态
2.1 了解多态
多态指的是⼀类事物有多种形态,(⼀个抽象类有多个⼦类,因⽽多态的概念依赖于继承)。
定义:多态是⼀种使⽤对象的⽅式,⼦类重写⽗类⽅法,调⽤不同⼦类对象的相同⽗类⽅法,可以
产⽣不同的执⾏结果
好处:调⽤灵活,有了多态,更容易编写出通⽤的代码,做出通⽤的编程,以适应需求的不断变
化!
实现步骤:
定义⽗类,并提供公共⽅法
定义⼦类,并重写⽗类⽅法
传递⼦类对象给调⽤者,可以看到不同⼦类执⾏效果不同
2.2 体验多态
class Dog(object):
 def work(self): # ⽗类提供统⼀的⽅法,哪怕是空⽅法

三. 类属性和实例属性
3.1 类属性
3.1.1 设置和访问类属性
类属性就是 类对象 所拥有的属性,它被 该类的所有实例对象 所共有。
类属性可以使⽤ 类对象 或 实例对象 访问。
 class Dog(object):
 def work(self): # ⽗类提供统⼀的⽅法,哪怕是空⽅法
12
三. 类属性和实例属性
3.1 类属性
3.1.1 设置和访问类属性
类属性就是 类对象 所拥有的属性,它被 该类的所有实例对象 所共有。
类属性可以使⽤ 类对象 或 实例对象 访问。
 
class Dog(object):
 def work(self): # ⽗类提供统⼀的⽅法,哪怕是空⽅法
        print('指哪打哪...')
class ArmyDog(Dog): # 继承Dog类
     def work(self): # ⼦类重写⽗类同名⽅法
         print('追击敌⼈...')
class DrugDog(Dog):
     def work(self):
         print('追查毒品...')
class Person(object):
     def work_with_dog(self, dog): # 传⼊不同的对象,执⾏不同的代码,即不同的work函数
             dog.work()
ad = ArmyDog()
dd = DrugDog()
daqiu = Person()
daqiu.work_with_dog(ad)
daqiu.work_with_dog(dd)


--》追击敌⼈...
追查毒品...




class Dog(object):
 tooth = 10
wangcai = Dog()
xiaohei = Dog()
print(Dog.tooth) # 10
print(wangcai.tooth) # 10
print(xiaohei.tooth) # 10

类属性的优点
记录的某项数据 始终保持⼀致时,则定义类属性。
实例属性 要求 每个对象 为其 单独开辟⼀份内存空间 来记录数据,⽽ 类属性 为全类所共有
,仅占⽤⼀份内存,更加节省内存空间。
3.1.2 修改类属性
类属性只能通过类对象修改,不能通过实例对象修改,如果通过实例对象修改类属性,表示的是创建了
⼀个实例属性。
3.2 实例属性
class Dog(object):
 tooth = 10
wangcai = Dog()
xiaohei = Dog()
# 修改类属性
Dog.tooth = 12
print(Dog.tooth) # 12
print(wangcai.tooth) # 12
print(xiaohei.tooth) # 12
# 不能通过对象修改属性,如果这样操作,实则是创建了⼀个实例属性
wangcai.tooth = 20
print(Dog.tooth) # 12
print(wangcai.tooth) # 20
print(xiaohei.tooth) # 12

class Dog(object):
 def __init__(self):
 self.age = 5
 def info_print(self):
 print(self.age)
wangcai = Dog()
print(wangcai.age) # 5
# print(Dog.age) # 报错:实例属性不能通过类访问
wangcai.info_print() # 5

四. 类⽅法和静态⽅法
4.1 类⽅法
4.1.1 类⽅法特点
需要⽤装饰器 @classmethod 来标识其为类⽅法,对于类⽅法,第⼀个参数必须是类对象,⼀般以
cls 作为第⼀个参数。
4.1.2 类⽅法使⽤场景
当⽅法中 需要使⽤类对象 (如访问私有类属性等)时,定义类⽅法
类⽅法⼀般和类属性配合使⽤
4.2 静态⽅法
4.2.1 静态⽅法特点
需要通过装饰器 @staticmethod 来进⾏修饰,静态⽅法既不需要传递类对象也不需要传递实例对象
(形参没有self/cls)。
静态⽅法 也能够通过 实例对象 和 类对象 去访问。
4.2.2 静态⽅法使⽤场景
当⽅法中 既不需要使⽤实例对象(如实例对象,实例属性),也不需要使⽤类对象 (如类属性、类⽅
法、创建实例等)时,定义静态⽅法
取消不需要的参数传递,有利于 减少不必要的内存占⽤和性能消耗
class Dog(object):
 __tooth = 10
 @classmethod
 def get_tooth(cls):
 return cls.__tooth
wangcai = Dog()
result = wangcai.get_tooth()
print(result) # 10

五. 总结
⾯向对象三⼤特性
封装
继承
多态
类属性
归属于类对象的属性,所有对象共有的属性
实例属性
类⽅法
静态⽅法
class Dog(object):
 @staticmethod
 def info_print():
 print('这是⼀个狗类,⽤于创建狗实例....')
wangcai = Dog()
# 静态⽅法既可以使⽤对象访问⼜可以使⽤类访问
wangcai.info_print()
Dog.info_print()

@classmethod
def xx():
 代码

@staticmethod
def xx():
 代码                 

创建classmethod时,该对象实例的class cls 是作为第一个输入变量的,而不是该实例本身(如果是实例本身的话,第一个输入变量就是self, 就是一个普通的我们常用的情况了)


这样创建的classmethod 有什么好处呢? 好处就是你可以直接用class来call这个函数,而不需要费周折地先去创建一个实例(class instance)。


而staticmethods呢,它没有默认的第一个输入变量。 它跟我们在一个空白的script里写的一个普通的函数 def fund():... 没有任何实质的区别。唯一的不同就是你要通过 类class 或者实例instance 来call它。

 

import time
 
 
class Date:
    def __init__(self,year,month,day):
        self.year = year
        self.month = month
        self.day = day
 
    @staticmethod
    def now():
        t = time.localtime()
        return Date(t.tm_year,t.tm_mon,t.tm_mday)
 
 
class EuroDate(Date):
    def __str__(self):
         return "year:%s month:%s day:%s" %(self.year,self.month,self.day)
 
 
e = EuroDate.now()
print(e)  #我们的意图是想触发EuroDate.__str__,但是结果为

 

# 代码的规范没有建立起来
from abc import ABCMeta,abstractmethod
class Payment(metaclass=ABCMeta):    # 抽象类

    @abstractmethod   # 如果我必须要实现pay方法,那么我需要给pay加一个装饰器
    def pay(self):
        pass   # 创建的这个pay并没有内容,
               # 之所以写一个pay是为了提醒所有子类你一定要实现一个pay方法

    @abstractmethod
    def back(self):
        pass

class Wechatpay(Payment):
    def __init__(self,name,money):
        self.name = name
        self.money = money
    def pay(self):
        print('%s通过微信支付了%s元'%(self.name,self.money))

class Alipay(Payment):
    def __init__(self,name,money):
        self.name = name
        self.money = money
    def pay(self):
        print('%s通过支付宝支付了%s元'%(self.name,self.money))

class ApplePay(Payment):
    def __init__(self, name, money):
        self.name = name
        self.money = money
    def pay(self):
        print('%s通过apple pay支付了%s元' % (self.name, self.money))
    def back(self):
        print('退款')

# 归一化设计
def pay(person):
    person.pay()

ApplePay('alex',20000)
抽象类 :Payment这个类是一个抽象类
抽象类做什么事儿 : 约束所有的子类 必须实现被abstractmethod装饰的方法名
                  给我们的代码指定规范
特点 : 抽象类不能实例化,只是作为具体的类的规范
抽象类长什么样
    class 类名(metaclass = 'ABCMeta'):

        @abstractmethod
        def 规定的方法名(self):pass

        @abstractmethod
        def 规定的方法名(self):pass

        
        @abstractmethod
        def 规定的方法名(self):pass
类只能单继承,所以抽象类 只能是所有的子类只有一个规范
# java 当中没有多继承的类
    # 接口 接口可以多继承
# 在python里没有接口的专用语法
    # 我们只是通过类的多继承 模仿接口的效果
from abc import ABCMeta,abstractmethod
class NormalAnnimal(metaclass=ABCMeta):
    @abstractmethod
    def eat(self):pass

    @abstractmethod
    def drink(self):pass
class FlyAnimal(metaclass=ABCMeta):
    @abstractmethod
    def fly(self):pass

class SwimAnimal(metaclass=ABCMeta):
    @abstractmethod
    def swim(self):pass

class WalkAnimal(metaclass=ABCMeta):
    @abstractmethod
    def walk(self):pass


class Frog(NormalAnnimal,SwimAnimal,WalkAnimal):
    def eat(self):
        pass


class Tiger(NormalAnnimal,SwimAnimal,WalkAnimal):pass
class Swan(NormalAnnimal,FlyAnimal,SwimAnimal,WalkAnimal):pass
class Parrot(NormalAnnimal,FlyAnimal,WalkAnimal):
    def talk(self):
        pass


# 抽象类 是单继承的规范
# 接口类 是多继承的规范

# java
    # 接口里面定义的所有的方法 都不能写具体的实现 pass
    # 抽象类里面定义的所有的抽象方法 内部是可以完成一些简单的代码

namedtuple

from collections import namedtuple

Course = namedtuple('Course',['name','price','period'])
python = Course('python',20000,'6 month')

print(python.name)
print(python.price)
print(python.period)
print(type(python))

print(python)
---->

python
20000
6 month
<class '__main__.Course'>
Course(name='python', price=20000, period='6 month')



 单例模式

Python单例模式的四种方法
在这之前,先了解super()和__new__()方法

super()方法:

返回一个父类或兄弟类类型的代理对象,让你能够调用一些从继承过来的方法。

它有两个典型作用:

a. 在单继承的类层次结构中,super()可用于引用父类而不显式父类名称,从而使代码更易于维护。

b. 在多重继承中,可以保证公共父类仅被执行一次。

__new__方法:

a.它是一个类级别的静态方法。通常用于控制生成一个新实例的过程。

b.返回的是一个实例化出来的实例

 

下面为四种实现单例模式的方法

1. 使用__new__方法

复制代码
class Singleton(object):
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, '_instance'):
            orig = super(Singleton, cls)
            cls._instance = orig.__new__(cls, *args, **kwargs)
        rerurn cls._instance

class A(Singleton):
    pass

# 类A即为单例类
复制代码
 

2.共享属性

复制代码
# 创建实例时把所有实例的__dict__指向同一个字典,这样它们都具有相同的属性和方法(类的__dict__存储对象属性)
class Singleton(object):
    _state = {}
    def __new__(cls, *args, **kwargs):
        ob = super(Singleton,cls).__new__(cls, *args, **kwargs)
        ob.__dict__ = cls._state
    return ob

class B(Singleton):
    pass

# 类B即为单例类
复制代码
 

3.使用装饰器

复制代码
def singleton(cls):
    instance = {}
    def wapper():
        if cls not in instance:
            instance[cls] = cls(*args, **kwargs)
        return instance[cls]
    return wapper

@singleton
class C:
    pass

# 类C即为单例类
复制代码
 

4.import方法

复制代码
# 作为Python模块时是天然的单例模式

#创建一个sington.py文件,内容如下:
    class Singleton(object):
        def foo(self):
            pass
    mysington = Singleton()

# 运用
from sington import mysington
mysington.foo()

 

posted on 2020-02-18 15:45  奇迹969  阅读(182)  评论(0)    收藏  举报

导航