• python面向对象的三大特性


    一、继承

    一、组合

    组合:组合指的是,在一个类中以另外一个类的对象(也就是实例)作为数据属性,称为类的组合

       也就是说:一个类的属性是另一个类的对象,就是组合

    例子:

      圆环是由两个圆组成的,圆环的面积就是外圆的面积减去内圆的面积。圆环的周长就是内圆的周长加上外圆的周长,这个时候,我们首先设计一个圆形类,计算一个圆的面积和圆的周长。然后在‘圆环类’组合圆形的实例作为自己的属性来用(这样的目的就是为了不用在写面积和周长的方法了,直接组合圆类的面积和方法去求解。减少了代码的重用)

    from math import pi
     2 class Circle:
     3     def __init__(self,r):
     4         self.r=r
     5     def perimater(self):
     6         return 2*pi*self.r
     7     def area(self):
     8         return pi*self.r*self.r
     9 # print(Circle.perimater('r',2))
    10 # print(Circle.area('r',3))
    11 
    12 
    13 class Circle_ring: #定义一个圆环类
    14     def __init__(self,outside_r,inside_r):
    15         outside_bijiao = max(outside_r,inside_r)
    16         intside_bijiao = min(outside_r, inside_r)
    17         self.outsize_circle = Circle(outside_bijiao) #实例化一个大圆形  作为self.outside_circle属性的值
    18         self.intsize_circle = Circle(intside_bijiao) #实例化一个小圆环
    19     def area(self):
    20         return self.outsize_circle.area()-self.intsize_circle.area()
    21     def perimater(self):
    22         return self.intsize_circle.perimater()+self.outsize_circle.perimater()
    23 
    24 
    25 r1 = Circle_ring(10,20)  #实例化
    26 print(r1.area())
    27 print(r1.perimater())

    组合的两种方式:1.在__init__方法里面组合
    2.在外面组合
    class BirthDate:
     2     def __init__(self,year,month,day):
     3         self.year=year
     4         self.month = month
     5         self.day = day
     6 class Course:
     7     def __init__(self,name,price,period): #period为周期
     8         self.name =name
     9         self.price = price
    10         self.period = period
    11 class Teacher:
    12     def __init__(self,name,salary,year,month,day,price,period): #那么这个里面也要把该有的属性传进去
    13         self.birth = BirthDate(year,month,day) #在里面组合(将BirthDate里面有的属性传入进去)
    14         self.course=Course(name,price,period)
    15         self.name = name
    16         self.salary = salary
    17 # 实例化方法一:
    18 egg = Teacher('egon',2000,1999,12,2,'6 months','15800')  #也要实例化,Teacher类里面的属性都得实例化
    19 print(egg.birth.month)  #当然老师也有生日,就让egg.birth.month
    20 print(egg.course.period)
    21 
    22 # 实例化方法二:
    23 egg.birth=BirthDate(1996,22,4)
    24 print(egg.birth.month)

    class BirthDate:
     2     def __init__(self,year,month,day):
     3         self.year=year
     4         self.month = month
     5         self.day = day
     6 class Course:
     7     def __init__(self,name,price,period): #period为周期
     8         self.name =name
     9         self.price = price
    10         self.period = period
    11 class Teacher:
    12     def __init__(self,name,salary,course):
    13         self.name = name
    14         self.salary = salary
    15         self.course = course
    16 #
    17 # #在外面组合。(组合就是一个类的属性是另一个类的对象)
    18 
    19 egg = Teacher('egon',2000,'python')
    20 egg.birth=BirthDate(1996,22,4) #直接给egg一个birth的属性,
    21 print(egg.birth.year)
    22 
    23 egg.course =Course('python','6 months',15800)
    24 print(egg.course.period)

    二、继承

    1.继承是一种创建新类的方式

    2.新建的类可以创建一个或多个父类,父类有称为基类或者超类

    3.新建的类称为派生类或者子类

    在python中类的继承分为:单继承或多继承

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class ParentClass1: #定义父类
        pass
     
    class ParentClass2: #定义父类
        pass
     
    class SubClass1(ParentClass1): #单继承,基类是ParentClass1,派生类是SubClass
        pass
     
    class SubClass2(ParentClass1,ParentClass2): #python支持多继承,用逗号分隔开多个继承的类
        pass

    4.查看所有继承的父类

    print(Person.__bases__)      #__base __只查看从左到右继承的第一个子类,__bases__则是查看所有继承的父类

    如果没有指定父类,python会默认继承object类,object是所有python的父类。

    经典类:在python2中,class Dad: 不会继承object,这样的类叫做经典类(它叫经典类,不是因为它经典,而是因为它比较老)

    新式类:在python3中,python会默认继承object类(一切皆对象)

        class Dad  就相当于python2中的  class Dad(object)  #新式类

    而且python3中没有经典类了

    5.继承与抽象(先抽象后继承)

    抽象:抽取类似或者说比较像的部分(也就是提取一类事物的特点,范围越来越大,共性越来越少)

        是从大范围到小范围的过程

    继承:是基于抽象的过程,通过编程语言去实现它,肯定是先经历抽象这个过程,才能通过继承的方式去表达出抽象的结构

          是从小范围到大范围的过程

    6.派生:(相对论)

      1.在父类的基础上产生子类,产生的子类就叫做派生类

      2.父类里没有的方法,在子类中有了,这样的方法就叫做派生方法。

      3.父类里有,子类也有的方法,就叫做方法的重写(就是把父类里的方法重写了)

    7.注意的几个概念:

      1.子类可以使用父类的所有属性和方法

      2.如果子类有自己的方法,就执行自己的;如果子类没有自己的方法,就会找父类的。

      3.如果子类里面没有找到,父类里也没有找到,就会报错

      4.如果子类中实现了调用父类的方法

        在类内:super(子类,self).方法名()  supper().__init__(参数)

        在类外:super(子类名,对象名).方法名()

    8.继承的实例

    class Animal:      #父类  基类  超类
     2     def __init__(self,name,life_value,aggr):
     3         self.name= name
     4         self.life_value = life_value
     5         self.aggr = aggr  #攻击力
     6     def eat(self):
     7         self.life_value += 10  #谁调谁的血量就增加
     8 
     9 class Person(Animal):  #子类  派生类
    10     def __init__(self, money, name, life_value, aggr):
    11         super().__init__(name, life_value, aggr)
    12         self.money = money  #派生出来的一个属性
    13     def attack(self,enemy):    #人的派生方法
    14         #enemy.life_value = enemy.life_value - self.aggr
    15         enemy.life_value -= self.aggr
    16 
    17 class Dog(Animal): #子类  派生类
    18     def __init__(self,name,breed, life_value,aggr):
    19         # Animal.__init__(self,name,breed, life_value,aggr)#让子类执行父类的方法 就是父类名.方法名(参数),连self都得传
    20         super().__init__(name,life_value,aggr) #super关键字  ,都不用传self了,在新式类里的
    21         # super(Dog,self).__init__(name,life_value,aggr)  #上面super是简写
    22         self.breed = breed
    23     def bite(self,person):   #狗的派生方法
    24         person.life_value -= self.aggr
    25     def eat(self):  #父类方法的重写
    26         super().eat()
    27         print('dog is eating')
    28 
    29 # ha2 = Dog('旺财','哈士奇',20000,100)
    30 # egg = Person('egon',500,1000,50)
    31 # print(egg.aggr)
    32 # print(ha2.aggr)
    33 # egg.eat()
    34 # print(egg.life_value)
    35 #
    36 # egg.eat()
    37 # print(egg.life_value)
    38 #
    39 # ha2.eat()
    40 # print(ha2.life_value)
    41 #
    42 # print(egg.life_value)
    43 # ha2.bite(egg)
    44 # print(egg.life_value)
    45 #
    46 
    47 ha2 = Dog('牛头梗','旺财',20000,100)
    48 print(ha2.life_value)
    49 ha2.eat()  #如果父类有的方法子类里面也有,那么就叫做方法的重写,就不执行父类的了,去执行子类了
    50 print(ha2.life_value)
    51 
    52 
    53 super(Dog,ha2).eat() #生掉父类的方法,但是不推荐这样用
    54 print(ha2.life_value)
    55 
    56 #在继承中,如果子类有的方法就执行子类的
    57 # 如果子类没有的方法就执行父类的

     继承的进阶

    一、复习

    面向对象

      1.类:具有相同属性和方法 的一类事物

         类名可以实例化一个对象

         类名可以调用类属性,(静态属性 和(方法)动态属性)

      2.对象:也就是实例

            对象名:调用对象属性

              调用方法

      3.什么叫抽象?

        从小到大的过程

      4.组合-----什么有什么的关系(将一个类的对象当做另一个类的属性)

      5.继承-----什么是什么的关系

          从大范围到小范围的过程

          继承的作用:减少代码的重用性

          子类有的方法,就用子类的。不会调用父类的方法。

          如果要在子类中调用父类的方法:super().类名()

      6.派生:父类没有的子类有了

          派生类:在父类的基础上,又产生了子类,这个子类就叫做派生类

          派生属性:父类里没有的属性但子类中有了的属性就叫做派生方法。

          派生方法:父类里没有的方法但子类中有了的方法就叫做派生方法。

      7.方法的重写

          父类里有子类里也有的方法叫做方法的重写

    二、接口类与抽象类

    1.接口类:(在抽象类的基础上)

        在python中,默认是没有接口类的

        接口类不能被实例化(如果实例化会报错)

        接口类中的方法不能被实现

    1.正常调用
     2 class Applepay:
     3     def pay(self,money):
     4         print('apple pay 支付了%s' %money)
     5 
     6 class Alipay:
     7     def pay(self,money):
     8         print('支付宝  支付了%s' %money)
     9 
    10 def payment(pay_obj,money):  #实例化的另一种调用,这个方法让实例化的时候按照payment调用:就像下面的payment(apple1,200)
    11         pay_obj.pay(money)
    12 
    13 apple1 = Applepay()
    14 # apple1.pay(200)
    15 payment(apple1,200)

    # 2.有时候写的时候会把方法写错,自己定义一个主动报错
     2 # 接口初成:手动报异常:NotImplementedError来解决开发中遇到的问题
     3 class Payment:
     4     def pay(self):
     5         raise NotImplementedError  #主动让程序报错
     6 
     7 class Wechatpay(Payment): #微信支付
     8     def pay(self,money):
     9         print('微信支付了%s元',money)
    10 
    11 class QQchatpay(Payment): #QQ支付
    12     def fuqian(self,money):
    13         print('QQ支付了%s元',money)
    14 
    15 p = Wechatpay()
    16 p.pay(200)   #不报错
    17 q = QQchatpay()   #不报错
    18 q.pay()  #报错

    # 3.借用abc模块来实现接口
     2 #接口类(就是为了提供标准,约束后面的子类)
     3 from abc import ABCMeta,abstractmethod
     4 class Payment(metaclass=ABCMeta):
     5     @abstractmethod
     6     def pay(self,money):
     7         pass
     8 
     9 class Wechatpay(Payment):
    10     def fuqian(self,money):
    11         '''实现了pay的功能,但是方法名字不一样'''
    12         print('微信支付了%s元'%money)
    13 
    14 class Alipay:
    15     def pay(self,money):
    16         print('支付宝  支付了%s' %money)
    17 
    18 # p = Wechatpay() #报错了(因为上面定义了一个接口类,接口类里面
    19 # 定义了一个pay方法,而在下面的Wechatpay方法里没有pay方法,不能
    20 # 调用,在接口类里面约束一下,接口类里的pay方法里面不能写其他,直接pass)
    21 a = Alipay()
    22 a.pay(200)
    23 p = Payment() #接口类不能被实例化

    接口提取了一群类共同的函数,可以把接口当做一个函数的集合。
     2 
     3 然后让子类去实现接口中的函数。
     4 
     5 这么做的意义在于归一化,什么叫归一化,就是只要是基于同一个接口实现的类,那么所有的这些类产生的对象在使用时,从用法上来说都一样。
     6 
     7 归一化,让使用者无需关心对象的类是什么,只需要的知道这些对象都具备某些功能就可以了,这极大地降低了使用者的使用难度。
     8 
     9 比如:我们定义一个动物接口,接口里定义了有跑、吃、呼吸等接口函数,这样老鼠的类去实现了该接口,松鼠的类也去实现了该接口,由二者分别产生一只老鼠和一只松鼠送到你面前,即便是你分别不到底哪只是什么鼠你肯定知道他俩都会跑,都会吃,都能呼吸。
    10 
    11 再比如:我们有一个汽车接口,里面定义了汽车所有的功能,然后由本田汽车的类,奥迪汽车的类,大众汽车的类,他们都实现了汽车接口,这样就好办了,大家只需要学会了怎么开汽车,那么无论是本田,还是奥迪,还是大众我们都会开了,开的时候根本无需关心我开的是哪一类车,操作手法(函数调用)都一样
    12 
    13 为何要用接口

    接口也就是做约束,让下面的类的方法都按照接口类中给出的方法去定义。如果接口类里面有的方法类里面没有,那么那个类就不能被实例化。(字面理解)

    继承的第二种含义非常重要。它又叫“接口继承”。
    接口继承实质上是要求“做出一个良好的抽象,这个抽象规定了一个兼容接口,使得外部调用者无需关心具体细节,可一视同仁的处理实现了特定接口的所有对象”——这在程序设计上,叫做归一化。

    2.抽象类:

        在python中,默认是有的

        父类的方法,子类必须实现

        抽象类(父类)的方法可以被实现

    # 抽象类
     2 # 什么叫做抽象?  从小范围到大范围
     3 from abc import ABCMeta,abstractmethod
     4 class Animal(metaclass=ABCMeta):
     5     @abstractmethod
     6     def eat(self):
     7         print('打开粮食的袋子')
     8         print('放一个吃饭的碗')
     9         print('吧粮食倒在碗里')
    10 
    11     @abstractmethod
    12     def sleep(self):
    13         pass
    14 
    15 class Dog(Animal):
    16     #实现吃喝睡的方法
    17     def eat(self):
    18         super().eat()
    19         # super(Dog, self).eat()
    20         print('dog is eating')
    21     def sleep(self):
    22         print('dog is sleeping')
    23 
    24 # d = Dog()
    25 # d.eat()
    26 a = Animal()  #抽象类不能被实例化

    3.抽象类和接口类的区别:接口类不能实现方法,抽象类可以实现方法里面的内容

    4.抽象类和接口类的相同点:都是用来做约束的,都不能被实例化

    5.抽象类和接口类的使用:

      当几个子类的父类有相同的功能需要被实现的时候就用抽象类

      当几个子类有相同的功能,但是实现各不相同的时候就用接口类

    6.python中的抽象类和接口类在Java里面的区别

      接口类支持多继承

      抽象类只支持单继承

    三、多继承

    在继承抽象类的过程中,我们应该尽量避免多继承;

    而在继承接口的时候,我们反而鼓励你来多继承接口

    class A:
     2     def test(self):
     3         print('from A')
     4 class B(A):
     5     def test(self):
     6         print('from B')
     7 class C(A):
     8     def test(self):
     9         print('from C')
    10 class D(A):
    11     def test(self):
    12         print('from D')
    13 class E(B):pass
    14     # def test(self):
    15     #     print('from E')
    16 
    17 class F(E,D,C):pass
    18     # def test(self):
    19         # print('from F')
    20 
    21 
    22 # b= B()
    23 # b.test()
    24 # d = D()
    25 # d.test() #一级一级往上找,自己没有,就继承爹的,爹没有就找爷爷的
    26         # 再找不到就报错了
    27 f = F()
    28 f.test()
    29 print(F.mro()) #查看找父类的顺序

    四、钻石继承

    新式类:广度优先:横着找(如钻石继承图,谁先在前面就找谁)

    经典类:深度优先:从上到下找

    五、多态

    多态指的是一类事物有多种形态(比如:老师.下课铃响了(),学生.下课铃响了(),老师执行的是下班操作,学生执行的是放学操作,虽然二者消息一样,但是执行的效果不同)

     例如:动物有多种形态:人,狗,猪

    from abc import ABCMeta,abstractmethod
     2 class Animal(metaclass=ABCMeta):
     3     @abstractmethod
     4     def eat(self):pass
     5 class Cat(Animal):  #动物的形态之一:猫
     6     def eat(self):
     7         print('cat eat')
     8 class Dog(Animal):  #动物的形态之二:狗
     9     def eat(self):
    10         print('dog eat')
    11 
    12 class Pig(Animal):pass  #动物的形态之三:猪
    13 def eat_fun(animal_obj): #定义一个函数让这个函数名去调用
    14     animal_obj.eat()
    15 c = Cat()
    16 eat_fun(c)  #函数名(对象)
    17 
    18 d = Dog() 
    19 eat_fun(d)
    20 
    21 c = Cat()
    22 c.eat()

    python自带多态:

      多态:同一类事物的多种状态

      python里处处都是多态,只是我们一般发现不了

      操作的时候不需要关心这个对象的数据类型,你只要用就行了

    静态多态性(了解就好)

    鸭子类型(如果两个类里面都有相同的方法,但是他们的类里面没有任何继承)
    序列(str,list,tuple):有顺序的数据集合,这三个没有任何继承

    封装

    补充封装:

    复制代码
    封装:
            体现在两点:
                1、数据的封装(将数据封装到对象中)
                    obj = Foo('宝宝',22)
                2、封装方法和属性,将一类操作封装到一个类中
    class Foo: def __init__(self,name,age): self.name = name self.age = age def show (self): print(self.name,self.age)
    复制代码

    什么是封装呢?(封装不是单纯意义的隐藏,其实它还是可以查看的)

      就是把一些不想让别人看的给隐藏起来了

    封装数据:目的是保护隐私

    功能封装:目的是隔离复杂度

    如果用了私有的,在类的外部,无法直接使用变形的属性,但是在类的内部可以直接使用

    1.用我们常用的__init__方法里的self取值
     2 class Course:#恰好给我们提供了实现这种思路的方法
     3 #             #一种思路,python
     4     def __init__(self,price,period,name):
     5         self.price = price
     6         self.period = period
     7         self.name = name
     8 c = Course(2000,'linux','6 months')
     9 print(c.period)
    10 
    11 2.在类里面定义一个空字典,然后装在字典里面取值
    12 def course(price,name ,period):
    13     dic = {}
    14     dic['price'] = price
    15     dic ['name'] = name
    16     dic ['period'] = period
    17     return dic
    18 
    19 c = Course(2000,'python','6 months')
    20 print(c.period)  #对象名.属性名     查看属性的值
    21 
    22 3.利用namedtuple方法
    23 from collections import namedtuple  #只有属性没有方法的类
    24 Course = namedtuple('Course',['name','price','period']) #传两个参数,第一个为自定义的名字,第二个传进去的是属性
    25 python = Course('python',10000,'6 moths')  #相当于实例化了
    26 print(python.name)

    2.封装类属性的私有属性(就是类属性前面加__)
    class Goods:
     2     # 按照打八折计算 (定义了一个私有类属性)
     3     __discount = 0.8  #变形后:_Goods__discount
     4     def __init__(self,name,price):
     5         self.name = name
     6         self.price = price
     7     def goods_price(self):
     8         return  self.price * Goods.__discount
     9 apple = Goods('apple',10)
    10 print(apple.goods_price())
    11 # print(Goods.__dict__)  #类名.__dict__
    12 print(Goods._Goods__discount)

    # 封装:把你不想让人看的隐藏起来
     2 # 数据封装:目的保护隐私
     3 class Teacher:
     4     __School = 'oldboy'  #类属性
     5     def __init__(self,name,salary):
     6         self.name = name
     7         self .__salary  =  salary  #_Teacher__salary
     8             # 老师的属性   值
     9         #怎么把薪水隐藏起来?
    10         self.__salary=salary
    11     def foo(self):
    12         print('------')
    13 
    14 t=Teacher('egon',2000)
    15 print(t.__dict__)
    16 # print(t.name)
    17 print(t._Teacher__salary)#让显示出来
    18 print(Teacher._Teacher__School)  #类属性使用_类名__属性名
    19 t.foo()
    20 #在本类内是可以正常调用的
    21 #在本类外就必须以_类名__属性名调用(但是不建议你调)

    3.封装类对象的私有属性

    1
    2
    3
    4
    5
    6
    7
    8
    成人的BMI数值:
    过轻:低于18.5
    正常:18.5-23.9
    过重:24-27
    肥胖:28-32
    非常肥胖, 高于32
      体质指数(BMI)=体重(kg)÷身高^2(m)
      EX:70kg÷(1.75×1.75=22.86

      如上面的指标来计算下你自己的体质指数

    class Person:
     2     def __init__(self,height,weight,name,sex):
     3         self.__height = height  #私有属性(让你不再外面调它)
     4                                 # 在本类中可以调用,在类外就不可以调用了
     5         self.__weigth = weight
     6         self.__name = name
     7         self.__sex = sex
     8     def tell_bmi(self):  #体重指数
     9         return self.__weigth/self.__height ** 2  #在本类中可以调用
    10         
    11     def tell_height(self):
    12         print(self.__height)
    13     def tell_weight(self):  #告诉体重
    14         return  self.__weigth
    15     def set_weigth(self,new_weight):   #修改体重
    16         if new_weight >20:
    17              self.__weigth = new_weight
    18         else:
    19             raise TypeError('你也太瘦了,瘦的连斤数都(快)没了')   #如果体重小于20或者负的,就主动提示一个报错
    20 egg = Person(1.6,96,'haiyan','female')
    21 print(egg.tell_bmi())
    22 # egg.__height #在类外不能调用
    23 # print(egg._Person__height)  #在类外查看得这样调用
    24 print(egg.__dict__)  #查看变形后的类型
    25 # egg.set_weigth(-10)
    26 # print(egg.tell_weigth())
    27 egg.set_weigth(66)  #修改体重为66
    28 print(egg.tell_weight())

    class People:
     2     def __init__(self,name,age,sex,height):
     3         self.__name = name
     4         self.__age = age
     5         self.__sex = sex
     6         self.__height = height
     7 
     8     def tell_name(self):  #看人名字
     9         print(self.name)
    10     def set_name(self,val): #修改名字
    11         if not isinstance(val, str):
    12             raise TypeError('名字必须是字符串类型')
    13         self.__name = val
    14     def tell_info(self):
    15          print('''
    16            ---------%s info-----------
    17            name:%s
    18            age:%s
    19            sex:%s
    20            height:%s'''%(self.__name,self.__name,self.__age,self.__sex,self.__height))
    21 
    22 p=People('egon',21,'male','180')
    23 p.tell_info()
    24 p.set_name('haiyan')   #调用修改名字的方法
    25 p.tell_info()
    26 # print(p._People__name)#就可以看到了

    4.封装类方法的私有属性
    # 方法的私有属性
     2 class Parent:
     3     def __init__(self):
     4         self.__func()  #__func==_Parent__func
     5     def __func(self):
     6         print('Parent func')
     7 
     8 class Son(Parent):
     9     def __init__(self):
    10         self.__func()  #_Son__func
    11     def __func(self):
    12         print('Son func')
    13 
    14     def _Parent__func(self):
    15         print('son _Parent__func')
    16 s = Son()
    17 print(Parent.__dict__)  #类名.__dict__查看变形后的结果
    18 
    19 # 私有属性:在本类内是可以正常调用的
    20 #           在本类外就必须以_类名__属性名调用(但是不建议你调)

    class Foo:
    2     def __func(self):
    3         print('from foo')
    4 class Bar(Foo):
    5     def __func(self):
    6         print('from bar')
    7 b = Bar()
    8 b._Foo__func()
    9 b._Bar__func()

    class Foo:
     2     def __init__(self,height,weight):
     3         self.height = height
     4         self.weight = weight
     5     def __heightpow(self):  #私有方法
     6         return self.height * self.height
     7     def tell_bmi(self):
     8         return self.weight/self.__heightpow()
     9 
    10 egon = Foo(1.7,120)
    11 print(egon.tell_bmi())
    12 print(Foo.__dict__)
    13 print(egon._Foo__heightpow())  #虽说是私有的,但是还是可以查看的

    5.property

    为什么要用property:将一个类的函数定义成特性以后,对象再去使用的时候obj.name,根本无法察觉自己的name是执行了一个函数然后计算出来的,这种特性的使用方式遵循了统一访问的原则

    1.计算圆的面积和周长

    from math import pi
     2 class Circle:
     3     def __init__(self,radius):
     4         self.radius = radius
     5     @property  #装饰器:把一个方法当成一个属性用了
     6     def area(self):
     7         return self.radius * self.radius* pi
     8     @property
     9     def peimeter(self):
    10         return 2*pi*self.radius
    11 
    12 c = Circle(10)
    13 print(c.area)  #当成一个属性来调了,就不用加括号了
    14 print(c.peimeter)

    2.缓存网页信息
    from urllib.request import urlopen
     2 class Web_page:
     3     def __init__(self,url):
     4         self.url = url
     5         self.__content = None  #内容设置为None
     6     @property
     7     def content(self):
     8         if self.__content:  #如果不为空,就说明已经下载了  _Web_page__content
     9             return self.__content
    10         else:
    11             self.__content = urlopen(self.url).read()#做缓存
    12             return self.__content
    13 mypage = Web_page('http://www.baidu.com')
    14 print(mypage.content)
    15 print(mypage.content)
    16 print(mypage.content)

    3.求和,平均值,最大值,最小值
    class Num:
     2     def __init__(self,*args):
     3         print(args)
     4         if len(args)==1 and (type(args[0]) is list or type(args[0]) is tuple):
     5             self.numbers=args[0]
     6         else:
     7             self.numbers = args
     8 
     9     @property
    10     def sum(self):
    11         return sum(self.numbers)
    12 
    13     @property
    14     def avg(self):
    15         return self.sum/len(self.numbers)
    16 
    17     @property
    18     def min(self):
    19         return min(self.numbers)
    20 
    21     @property
    22     def max(self):
    23         return max(self.numbers)
    24 num = Num([3,1,3])
    25 vvv = Num(8,2,3)
    26 print(num.sum)
    27 print(num.min)
    28 print(num.avg)
    29 print(num.max)
    30 print('-----------')
    31 print(vvv.sum)
    32 print(vvv.min)
    33 print(vvv.avg)
    34 print(vvv.max)

     6.setter
     class Goods:
     2     __discount = 0.8  #类的私有属性
     3     def __init__(self,name,price):
     4         self.name = name
     5         self.__price = price
     6 
     7     @property
     8     def price(self):
     9         # if hasattr(self,'__price'):
    10             return self.__price * Goods.__discount
    11         # else:
    12         #     raise NameError
    13 
    14     @price.setter
    15     def price(self,new_price):
    16         if type(new_price) is int:
    17             self.__price = new_price
    18 
    19     @price.deleter
    20     def price(self):
    21         del self.__price
    22 
    23 apple = Goods('apple',10)
    24 # print(apple.price)
    25 apple.price = 20
    26 print(apple.price)
    27 
    28 # del apple.price
    29 # print(apple.price)
    30 # apple.set_price(20)
    31 # apple._Goods__apple

    @property把一个类中的方法 伪装成属性
    原来是obj.func()
    现在是obj.func -->属性
    1.因为属性不能被修改
    所以用了@funcname.setter
    obj.func = new_value 调用的是被@funcname.setter装饰器装饰的方法
    被@property装饰的方法名必须和被@funcname.setter装饰的方法同名
    2.也可以另一种方法修改,但是上一种方法吧一个类中的方法伪装成属性来调用了,而这种方法
    还是原来实例化一样调用
    例如:
    class People:
     2     def __init__(self,name,age,sex,height):
     3         self.__name = name
     4         self.__age = age
     5         self.__sex = sex
     6         self.__height = height
     7 
     8     def tell_name(self):  #看人名字
     9         print(self.name)
    10     def set_name(self,val): #修改名字
    11         if not isinstance(val, str):
    12             raise TypeError('名字必须是字符串类型')
    13         self.__name = val
    14     def tell_info(self):
    15          print('''
    16            ---------%s info-----------
    17            name:%s
    18            age:%s
    19            sex:%s
    20            height:%s'''%(self.__name,self.__name,self.__age,self.__sex,self.__height))
    21 
    22 p=People('egon',21,'male','180')
    23 p.tell_info()
    24 p.set_name('haiyan')   #调用修改名字的方法
    25 p.tell_info()
    26 # print(p._People__name)#就可以看到了
    
    
     
  • 相关阅读:
    LeetCode 121. Best Time to Buy and Sell Stock
    LeetCode 221. Maximal Square
    LeetCode 152. Maximum Product Subarray
    LeetCode 53. Maximum Subarray
    LeetCode 91. Decode Ways
    LeetCode 64. Minimum Path Sum
    LeetCode 264. Ugly Number II
    LeetCode 263. Ugly Number
    LeetCode 50. Pow(x, n)
    LeetCode 279. Perfect Squares
  • 原文地址:https://www.cnblogs.com/intruder/p/10928820.html
Copyright © 2020-2023  润新知