• 类和对象


    1.类的组成    数据和函数,二者是类的属性

    2.两个作用: 实例化 属性引用  

       属性引用:类名.属性(增删改查) 

       实例化: 类名加括号就是实例化,会自动出发__init__的运行,可以用它为每个实例创建自己的特征

    类属性     特征(变量)
              技能(函数)
    
    对象属性:对象本身只有特征(变量)
    class Province:
        memo = "中国的23个省之一"                    #类的数据属性
     
        def __init__(self,name,capital,leader):
            self.Name = name
            self.Capital = capital
            self.Leadder = leader
     
        def sport_meet(self):
            print('%s 正在开运动会'% self.Name)
     
        def pao(self,pao):
            print('%s 正在放%s炮'% (self.Name,pao))
     
     
    -------------------类--------------------
     
    print(Province.__dict__)         #查看类属性字典
     
    print(Province.memo)             #查看类的数据属性
        中国的23个省之一
    print(Province.__dict__["memo"]) #查看类的数据属性
        中国的23个省之一
     
    Province.sport_meet("山西")               #查看类的函数属性
            正在开运动会
    Province.__dict__["sport_meet"]("山西")   #查看类的函数属性
            正在开运动会
    ---------------------------------------
     
    --------------类的其它属性------------------
     
    类名.__name__     # 类的名字(字符串)
    类名.__doc__      # 类的文档字符串
    类名.__base__     # 类的第一个父类(在讲继承时会讲)
    类名.__bases__    # 类所有父类构成的元组(在讲继承时会讲)
    类名.__dict__     # 类的字典属性
    类名.__module__   # 类定义所在的模块
    类名.__class__    # 实例对应的类(仅新式类中)
     
    ------------------------------------------
     
     
    # ----------------------对象--------------------
     
    hb = Province('河北','石家庄','李杨')            #创建实例
    print(hb.__dict__)
        {'Capital': '石家庄', 'Leadder': '李杨', 'Name': '河北'}
     
    print(hb.memo)          #实例调取类的数据属性
        中国的23个省之一
     
    hb.sport_meet()         #实例调取没有参数的函数
        河北 正在开运动会
     
    hb.pao("")           #实例调取有参数的函数
        河北 正在放大炮
    类和对象分别调用 特征和函数
     1 class Chinese:
     2     country="china"
     3     def __init__(self,name):
     4         self.name=name
     5 
     6     def play_ball(self,ball):
     7         print("%s 正在打 %s" %(self.name,ball))
     8 
     9 p1=Chinese("alex")
    10 
    11 #对象执行类的数据属性
    12 # print(p1.country)
    13 #     china
    14 
    15 
    16 #对象改p1.country="日本",相当于给对象的__dict__增加值,而不是改变类的数据属性
    17 print(p1.__dict__)
    18     # {'name': 'alex'}
    19 p1.country="日本"
    20 print(p1.__dict__)
    21     # {'name': 'alex', 'country': '日本'}
    22 print(p1.country)
    23     # 日本
    24 print(Chinese.country)
    25     #china
    View Code
     1 #类里面的数据属性contry只会被Chinese.country和p1.country调用到
     2 country = "日本"
     3 
     4 class Chinese:
     5     country = "china"       #只会被类和对象调用到,带点的
     6 
     7     def __init__(self,name):
     8         self.name=name
     9         print(country)      #此时的country就是一个普通的变量
    10 
    11     def play_ball(self,ball):
    12         print("%s 正在打 %s" %(self.name,ball))
    13 
    14 p1=Chinese("alex")
    15     #日本
    View Code
     1 #p1.l1 = [1,2,3]相当于给p1__dict__增加
     2 # p1.l1.append(5)相当于给原来的l1追加,相当于操作的是类
     3 class Chinese:
     4     l1 = ["alex","egon"]
     5     def __init__(self,name):
     6         self.name=name
     7 
     8 
     9     def play_ball(self,ball):
    10         print("%s 正在打 %s" %(self.name,ball))
    11 
    12 p1=Chinese("alex")
    13 
    14 
    15 p1.l1 = [1,2,3]
    16 print(Chinese.l1)
    17     #['alex', 'egon']
    18 
    19 #追加之后发现原来的l1也变了
    20 p1.l1.append(5)
    21 print(p1.l1)
    22     #['alex', 'egon', 5]
    23 print(Chinese.l1)
    24     #['alex', 'egon', 5]
    View Code

    静态方法  staticmethod

    #静态方法,此时对象调类里面的函数不是绑定方法,而是普通的函数
    
    class Foo:
        @staticmethod
        def spam(x,y,z):    #没有self,即使有self,也会当成普通参数
            print(x,y,z)
    
    f2=Foo()
    f2.spam(1,2,3)
    Example 1 @staticmethod
     import time
    class Date:
        def __init__(self,year,month,day):
            self.year=year
            self.month=month
            self.day=day
        @staticmethod
        def now():                 #用Date.now()的形式去产生实例,该实例用的是当前时间
            t=time.localtime()     #获取结构化的时间格式
            obj=Date(t.tm_year,t.tm_mon,t.tm_mday) #新建实例并且返回
            return obj
    
    #之前实例化
    # d1=Date(2017,1,13)
    # print(d1.year,d1.month,d1.day)
    #     2017 1 13
    
    #现在实例化,不需要传值
    # data_now = Date.now()
    # print(data_now.year,data_now.month,data_now.day)
    #     2017 4 22
    应用场景

    类方法  classmethod

      把一个方法绑定给类:类.绑定到类的方法(),会把类本身当做第一个参数自动传给绑定到类的方法

    class Foo:
    
        @classmethod #把一个方法绑定给类:类.绑定到类的方法(),会把类本身当做第一个参数自动传给绑定到类的方法
        def test(cls,x):
            print(cls,x) #拿掉一个类的内存地址后,就可以实例化或者引用类的属性了
    
    
    
    Foo.test(123)
        <class '__main__.Foo'> 123
    
    
    f = Foo()
    print(f.test)       # 发现现在对象调时候成了类的绑定方法
        <bound method Foo.test of <class '__main__.Foo'>>
    f.test(123)         #现在对象传值的时候第一个传的默认是类
        <class '__main__.Foo'> 123
    Example 1 @classmethod
    #__str__定义在类内部,必须返回一个字符串类型,
    #什么时候会触发它的执行呢?打印由这个类产生的对象时,会触发执行
    
    class People:
        def __init__(self,name,age):
            self.name=name
            self.age=age
        def __str__(self):
            return 'name:%s,age:%s' %(self.name,self.age)
    
    p1=People('egon',18)
    print(p1)
    
    
    
    import time
    class Date:
        def __init__(self,year,month,day):
            self.year=year
            self.month=month
            self.day=day
    
        @classmethod
        def now(cls): #用Date.now()的形式去产生实例,该实例用的是当前时间
            t=time.localtime() #获取结构化的时间格式
            obj=cls(t.tm_year,t.tm_mon,t.tm_mday) #新建实例并且返回
            return obj
    
    
    class EuroDate(Date):
        def __str__(self):
            return '年:%s,月:%s,日:%s' %(self.year,self.month,self.day)
    
    e1=EuroDate.now()
    print(e1)
    应用场景 
    在类内部定义的函数无非三种用途
    一:绑定到对象的方法
    	只要是在类内部定义的,并且没有被任何装饰器修饰过的方法,都是绑定到对象的
    	
    	class Foo:
    		def test(self): #绑定到对象的方法
    			pass
    		def test1(): #也是绑定到对象的方法,只是对象.test1(),会把对象本身自动传给test1,因test1没有参数所以会抛出异常
    			pass
    	
    	绑定到对象,指的是:就给对象去用,
    	使用方式:对象.对象的绑定方法(),不用为self传值
    	特性:调用时会把对象本身当做第一个参数传给对象的绑定方法
    	
    
    	
    二:绑定到类的方法:classmethod
    	在类内部定义的,并且被装饰器@classmethod修饰过的方法,都是绑定到类的
    	
    	class Foo:
    		def test(self): #绑定到对象的方法
    			pass
    		def test1(): #也是绑定到对象的方法,只是对象.test1(),会把对象本身自动传给test1,因test1没有参数所以会抛出异常
    			pass
    	
    	绑定到对象,指的是:就给对象去用,
    	使用方式:对象.对象的绑定方法()
    	特性:调用时会把对象本身当做第一个参数传给对象的绑定方法
    	
    	
    三:解除绑定的方法:staticmethod
    	既不与类绑定,也不与对象绑定,不与任何事物绑定
    	绑定的特性:自动传值(绑定到类的就是自动传类,绑定到对象的就自动传对象)
    	解除绑定的特性:不管是类还是对象来调用,都没有自动传值这么一说了
    	
    	所以说staticmethod就是相当于一个普通的工具包
    	
    	
    class Foo:
    	def test1(self):
    		pass
    	def test2():
    		pass
    	
    
    	
    	@classmethod
    	def test3(cls):
    		pass
    	@classmethod
    	def test4():
    		pass
    		
    		
    		
    	@staticmethod
    	def test5():
    		pass
    		
    test1与test2都是绑定到对象方法:调用时就是操作对象本身
    	<function Foo.test1 at 0x0000000000D8E488>
    	<function Foo.test2 at 0x0000000000D8E510>
    test3与test4都是绑定到类的方法:调用时就是操作类本身
    	<bound method Foo.test3 of <class '__main__.Foo'>>
    	<bound method Foo.test4 of <class '__main__.Foo'>>
    test5是不与任何事物绑定的:就是一个工具包,谁来都可以用,没说专门操作谁这么一说
    	<function Foo.test5 at 0x0000000000D8E6A8>
    

      

    面向对象的三大特性 

    一.继承 

    继承 

      继承是一种创建新的类的方式,在python中,新建的类可以继承自一个或者多个父类,原始类称为基类或超类,新建的类称为派生类或子类。 

      python中类的继承分为:单继承和多继承

      继承有两种用途:  

      1:继承基类的方法,并且做出自己的改变或者扩展(代码重用)

      2:声明某个子类兼容于某基类,定义一个接口类Interface,接口类中定义了一些接口名(就是函数名)且并未实现接口的功能,子类继承接口类,

        并且实现接口中的功能

     1 class Animal:
     2 
     3     def eat(self):
     4         print "%s 吃 " %self.name
     5 
     6     def drink(self):
     7         print "%s 喝 " %self.name
     8 
     9     def shit(self):
    10         print "%s 拉 " %self.name
    11 
    12     def pee(self):
    13         print "%s 撒 " %self.name
    14 
    15 
    16 class Cat(Animal):
    17 
    18     def __init__(self, name):
    19         self.name = name
    20         self.breed = ''
    21 
    22     def cry(self):
    23         print '喵喵叫'
    24 
    25 class Dog(Animal):
    26     
    27     def __init__(self, name):
    28         self.name = name
    29         self.breed = ''
    30         
    31     def cry(self):
    32         print '汪汪叫'
    33         
    34 
    35 # ######### 执行 #########
    36 
    37 c1 = Cat('小白家的小黑猫')
    38 c1.eat()
    39 
    40 c2 = Cat('小黑的小白猫')
    41 c2.drink()
    42 
    43 d1 = Dog('胖子家的小瘦狗')
    44 d1.eat()
    继承

     组合

      软件重用的重要方式除了继承之外还有另外一种方式,即:组合

      组合指的是,在一个类中以另外一个类的对象作为数据属性,称为类的组合

    class Teacher:
        def __init__(self,name,sex,course):
            self.name=name
            self.sex=sex
            self.course=course
    class Student:
        def __init__(self,name,sex,course):
            self.name=name
            self.sex=sex
            self.course=course
    class Course:
        def __init__(self,name,price,peroid):
            self.name=name
            self.price=price
            self.period=peroid
    python_obj=Course('python',15800,'7m')
    t1=Teacher('egon','male',python_obj)
    s1=Student('cobila','male',python_obj)
    
    print(s1.course.name)
    print(t1.course.name)
    学生老师和成绩组合

    组合与继承  

      组合对比继承来说,也是用来重用代码,但是组合描述的是一种“有”的关系

      都是有效地利用已有类的资源的重要方式。但是二者的概念和使用场景皆不同  

      1.继承的方式

        通过继承建立了派生类与基类之间的关系,它是一种'是'的关系,比如白马是马,人是动物。 

        当类之间有很多相同的功能,提取这些共同的功能做成基类,用继承比较好,比如教授是老师

      2.组合的方式

        用组合的方式建立了类与组合的类之间的关系,它是一种‘有’的关系,比如教授有生日,教授教python课程  

    老师有课程
    学生有成绩
    学生有课程
    学校有老师
    学校有学生
    
    class Course:
        def __init__(self,name,price,period):
            self.name=name
            self.price=price
            self.period=period
            
    class Teacher:
        def __init__(name,course):
            self.name=name
            self.course=course
            
    class Student:
        def __init__(name,course):
            self.name=name
            self.course=course
    
    python=Course('python',15800,'7m')
    t1=Teacher('egon',python)
    s1=Student('alex',python)
    
    
    print(s1.course.name)
    print(s1.course.period)
    组合 

    派生 

      子类继承了父类的属性,然后衍生出自己新的属性,如果子类衍生出的新的属性与父类的某个属性名字相同,
      那么再调用子类的这个属性,就以子类自己这里的为准了

    class People:
        def __init__(self,name,sex,age):
            self.name=name
            self.age=age
            self.sex=sex
    
        def walk(self):
            print('%s is walking' %self.name)
    
    
    class Chinese(People):
        country='China'
        def __init__(self,name,sex,age,language='Chinese'):
            People.__init__(self,name,sex,age)
            self.language=language
    
        def walk(self):
            People.walk(self)
    
    class North_korean(People):
        country='Korean'
    
    
    c=Chinese('egon','male',18)
    print(c.name,c.age,c.sex)
        egon 18 male
    print(c.__dict__)
        {'sex': 'male', 'age': 18, 'language': 'Chinese', 'name': 'egon'}
    print(c.country)
        China
    c.walk()
        egon is walking
    派生

    接口与归一化设计 

      1.接口

      为何要用接口:

        接口提取了一群类共同的函数,可以把接口当做一个函数的集合。

        然后让子类去实现接口中的函数。

        这么做的意义在于归一化,什么叫归一化,就是只要是基于同一个接口实现的类,那么所有的这些类产生的对象在使用时,从用法上来说都一样。 

        归一化,让使用者无需关心对象的类是什么,只需要的知道这些对象都具备某些功能就可以了,这极大地降低了使用者的使用难度。

    class Interface:#定义接口Interface类来模仿接口的概念,python中压根就没有interface关键字来定义一个接口。
        def read(self): #定接口函数read
            pass
    
        def write(self): #定义接口函数write
            pass
    
    
    class Txt(Interface): #文本,具体实现read和write
        def read(self):
            print('文本数据的读取方法')
    
        def write(self):
            print('文本数据的读取方法')
    
    class Sata(Interface): #磁盘,具体实现read和write
        def read(self):
            print('硬盘数据的读取方法')
    
        def write(self):
            print('硬盘数据的读取方法')
    
    class Process(All_file):
        def read(self):
            print('进程数据的读取方法')
    
        def write(self):
            print('进程数据的读取方法')
    文件和程序的读写 接口设计   

       2.抽象类

      1 什么是抽象类

          与java一样,python也有抽象类的概念但是同样需要借助模块实现,抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化

      2 为什么要有抽象类

          如果说类是从一堆对象中抽取相同的内容而来的,那么抽象类是从一堆中抽取相同的内容而来的,内容包括数据属性和函数属性。

    import abc
    #抽象类:本质还是类,与普通类额外的特点的是:加了装饰器的函数,子类必须实现他们
    class Animal(metaclass=abc.ABCMeta):
        tag='123123123123123'
        @abc.abstractmethod
        def run(self):
            pass
        @abc.abstractmethod
        def speak(self):
            pass
    
    
    
    class People(Animal):
        def run(self):
            pass
    
        def speak(self):
            pass
    
    
    peo1=People()
    print(peo1.run)
    抽象类 import abc 
     1 #_*_coding:utf-8_*_
     2 __author__ = 'Linhaifeng'
     3 #一切皆文件
     4 import abc #利用abc模块实现抽象类
     5 
     6 class All_file(metaclass=abc.ABCMeta):
     7     all_type='file'
     8     @abc.abstractmethod #定义抽象方法,无需实现功能
     9     def read(self):
    10         '子类必须定义读功能'
    11         pass
    12 
    13     @abc.abstractmethod #定义抽象方法,无需实现功能
    14     def write(self):
    15         '子类必须定义写功能'
    16         pass
    17 
    18 # class Txt(All_file):
    19 #     pass
    20 #
    21 # t1=Txt() #报错,子类没有定义抽象方法
    22 
    23 class Txt(All_file): #子类继承抽象类,但是必须定义read和write方法
    24     def read(self):
    25         print('文本数据的读取方法')
    26 
    27     def write(self):
    28         print('文本数据的读取方法')
    29 
    30 class Sata(All_file): #子类继承抽象类,但是必须定义read和write方法
    31     def read(self):
    32         print('硬盘数据的读取方法')
    33 
    34     def write(self):
    35         print('硬盘数据的读取方法')
    36 
    37 class Process(All_file): #子类继承抽象类,但是必须定义read和write方法
    38     def read(self):
    39         print('进程数据的读取方法')
    40 
    41     def write(self):
    42         print('进程数据的读取方法')
    43 
    44 wenbenwenjian=Txt()
    45 
    46 yingpanwenjian=Sata()
    47 
    48 jinchengwenjian=Process()
    49 
    50 #这样大家都是被归一化了,也就是一切皆文件的思想
    51 wenbenwenjian.read()
    52 yingpanwenjian.write()
    53 jinchengwenjian.read()
    54 
    55 print(wenbenwenjian.all_type)
    56 print(yingpanwenjian.all_type)
    57 print(jinchengwenjian.all_type)
    接口继承

    2 继承顺序原理(python如何实现的继承)

    python到底是如何实现继承的,对于你定义的每一个类,python会计算出一个方法解析顺序(MRO)列表,这个MRO列表就是一个简单的所有基类的线性顺序列表,例如

    >>> F.mro() #等同于F.__mro__
    [<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]

    为了实现继承,python会在MRO列表上从左到右开始查找基类,直到找到第一个匹配这个属性的类为止。
    而这个MRO列表的构造是通过一个C3线性化算法来实现的。我们不去深究这个算法的数学原理,它实际上就是合并所有父类的MRO列表并遵循如下三条准则:
    1.子类会先于父类被检查
    2.多个父类会根据它们在列表中的顺序被检查
    3.如果对下一个类存在两个合法的选择,选择第一个父类

     1 class A(object):
     2     def test(self):
     3         print('from A')
     4 
     5 class B(A):
     6     def test(self):
     7         print('from B')
     8 
     9 class C(A):
    10     def test(self):
    11         print('from C')
    12 
    13 class D(B):
    14     def test(self):
    15         print('from D')
    16 
    17 class E(C):
    18     def test(self):
    19         print('from E')
    20 
    21 class F(D,E):
    22     # def test(self):
    23     #     print('from F')
    24     pass
    25 f1=F()
    26 f1.test()
    27 print(F.__mro__) #只有新式才有这个属性可以查看线性列表,经典类没有这个属性
    28 
    29 #新式类继承顺序:F->D->B->E->C->A
    30 #经典类继承顺序:F->D->B->A->E->C
    31 #python3中统一都是新式类
    32 #pyhon2中才分新式类与经典类
    继承顺序

    3.子类调用父类的方法

    子类继承了父类的方法,然后想进行修改,注意了是基于原有的基础上修改,那么就需要在子类中调用父类的方法

    方法一:父类名.父类方法()

     1 class Vehicle: #定义交通工具类
     2      Country='China'
     3      def __init__(self,name,speed,load,power):
     4          self.name=name
     5          self.speed=speed
     6          self.load=load
     7          self.power=power
     8 
     9      def run(self):
    10          print('开动啦...')
    11 
    12 class Subway(Vehicle): #地铁
    13     def __init__(self,name,speed,load,power,line):
    14         Vehicle.__init__(self,name,speed,load,power)
    15         self.line=line
    16 
    17     def run(self):
    18         print('地铁%s号线欢迎您' %self.line)
    19         Vehicle.run(self)
    20 
    21 line13=Subway('中国地铁','180m/s','1000人/箱','',13)
    22 line13.run()
    View Code

    方法二:super()

    super在python2中的用法:
        1:super(自己的类,self).父类的函数名字
        2:super只能用于新式类
    class People(object):
        def __init__(self,name,sex,age):
            self.name=name
            self.age=age
            self.sex=sex
        def walk(self):
            print('%s is walking' %self.name)
    class Chinese(People):
        country='China'
        def __init__(self,name,sex,age,language='Chinese'):
            super(Chinese,self).__init__(name,sex,age)
            self.language=language
    c=Chinese('egon','male',18)
    print c.name,c.age,c.sex,c.language
    python2 supper
    class People:
        def __init__(self,name,sex,age):
            self.name=name
            self.age=age
            self.sex=sex
        def walk(self):
            print('%s is walking' %self.name)
    class Chinese(People):
        country='China'
        def __init__(self,name,sex,age,language='Chinese'):
            # self.name=name
            # self.sex=sex
            # self.age=age
            # People.__init__(self,name,sex,age)
            super(Chinese,self).__init__(name,sex,age)
            self.language=language
        def walk(self,x):
            super().walk()
            print('子类的x',x)
    c=Chinese('egon','male',18)
    print(c.name,c.age,c.sex,c.language)
    c.walk(123)
    python3 supper

     二.多态

    多态指的是一类事物有多种形态,(一个抽象类有多个子类,因而多态的概念依赖于继承)

      1. 序列类型有多种形态:字符串,列表,元组。

      2. 动物有多种形态:人,狗,猪

      3. 文件有多种形态:文件文件,可执行文件

    import abc
    class Animal(metaclass=abc.ABCMeta): #同一类事物:动物
        @abc.abstractmethod
        def talk(self):
            pass
    
    class People(Animal): #动物的形态之一:人
        def talk(self):
            print('say hello')
    
    class Dog(Animal): #动物的形态之二:狗
        def talk(self):
            print('say wangwang')
    
    class Pig(Animal): #动物的形态之三:猪
        def talk(self):
            print('say aoao')
    动物多态
    import abc
    class File(metaclass=abc.ABCMeta): #同一类事物:文件
        @abc.abstractmethod
        def click(self):
            pass
    
    class Text(File): #文件的形态之一:文本文件
        def click(self):
            print('open file')
    
    class ExeFile(File): #文件的形态之二:可执行文件
        def click(self):
            print('execute file')
    文件有多种形态:文件文件,可执行文件 

    多态性

    同一种调用方式,不同的调用效果

    多态性是指具有不同功能的函数可以使用相同的函数名,这样就可以用一个函数名调用不同内容的函数。 

    在面向对象方法中一般是这样表述多态性:向不同的对象发送同一条消息,不同的对象在接收时会产生不同的行为(即方法)。也就是说,每个对象可以用自己的方式去响应共同的消息。所谓消息,就是调用函数,不同的行为就是指不同的实现,即执行不同的函数。

    综上我们也可以说,多态性是‘一个接口(函数func)

    class Animal:
        def run(self):
            raise AttributeError('子类必须实现这个方法')
    
    
    class People(Animal):
        def run(self):
            print('people is walking')
    
    class Pig(Animal):
        def run(self):
            print('pig is walking')
    
    
    class Dog(Animal):
        def run(self):
            print('dog is running')
    
    peo1=People()
    pig1=Pig()
    ------------------人和猪都有run方法---------
    peo1.run()
    pig1.run()
        people is walking
        pig is walking
    
    -----------------多态性,函数把run方法包装------------
    多态性:定义统一的接口,可以传入不同类型的值,但是调用的逻辑都一样,执行的结果却不一样
    def Run(name):
        name.run()
    
    Run(peo1)
    Run(pig1)
        people is walking
        pig is walking
    多态性

     三.封装

      为什么要封装

        封装数据的主要原因是:保护隐私(作为男人的你,脸上就写着:我喜欢男人,你害怕么?)

        封装方法的主要原因是:隔离复杂度(快门就是傻瓜相机为傻瓜们提供的方法,该方法将内部复杂的照相功能都隐藏起来了

                                                          比如你不必知道你的鸟是怎出来的,你直接掏出自己的接口就能用尿这个功能)

      封装的两个层面 

        1.第一个层面的封装:(什么都不用做):创建类和对象会分别创建二者的名称空间,我们只能用类名.或者obj.的方式去访问里面的名字,这本身就是一种                 封装  

        2.第二个层面的封装:类中把某些属性和方法隐藏起来(或者说定义成私有的),只在类的内部使用、外部无法访问,或者留下少量接口(函数)供外部访问 

    class A:
        __x = 1             #转换为_A__x
        def __test(self):
            print("from A")
    
    print(A.__dict__)
        {   '_A__x': 1  }
    
    ------查看类的隐藏属性————
    
    obj = A()
    print(A._A__x)
        1
    print(obj._A__x)
        1
    A._A__test(123)
        from A
    obj._A__test()
        from A
    封装

       特性(property)

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

    import math
    class Circle:
        def __init__(self,radius): #圆的半径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(10)
    print(c.radius)
    print(c.area)         #可以向访问数据属性一样去访问area,会触发一个函数的执行,动态计算出一个值
    print(c.perimeter)
    -----------------------执行结果--------
    10
    314.1592653589793
    62.83185307179586
    property
    class People:
        def __init__(self,name,age,height,weight):
            self.name=name
            self.age=age
            self.height=height
            self.weight=weight
        @property
        def bodyindex(self):
            return self.weight/(self.height**2)
    
    
    p1=People('cobila',38,1.65,74)
    print(p1.bodyindex)
    p1.weight=200
    print(p1.bodyindex)
    
    ------------------------结果---------
    
    27.180899908172638
    73.46189164370983
    BMI 指数
    class People:
        def __init__(self,name):
            self.__name = name
    
        @property
        def name(self):
            return self.__name
    
    p1 = People("egon")
    print(p1.name)      #会找含有@property下name的函数
    
    -----------------------------
    egon
    @property 查找 
    class People:
        def __init__(self,name,Sex):
            self.name = name
            self.__sex = Sex
    
        @property
        def sex(self):
            return self.__sex
    
        @sex.setter
        def sex(self,value):
            self.__sex = value
    
    p1 = People("egon","male")
    print(p1.sex)      #会找含有@property下name的函数
    
    p1.sex = "famale"  #修改会找@sex.setter下的函数
    print(p1.sex)
    
    ---------------------
    male
    famale
    
    
    
    #修改性别,判断性别如果不为字符串,就报错
    class People:
        def __init__(self,name,Sex):
            self.name = name
            self.__sex = Sex
    
        @property
        def sex(self):
            return self.__sex
    
        @sex.setter
        def sex(self,value):
            if not isinstance(value,str):      #如果性别不为字符串,就报错
                raise TypeError("性别必须为字符串")
            self.__sex = value
    
    p1 = People("egon","male")
    p1.sex = 123           #修改会找@sex.setter下的函数
    print(p1.sex)
    
    -----------------
    TypeError: 性别必须为字符串
    
    
    
    
    # 实例化时后,如果不是字符串,也报错
    class People:
        def __init__(self,name,Sex):
            self.name = name
            self.sex = Sex      #此时是self.sex,而不是self.__sex
    
        @property
        def sex(self):
            return self.sex
    
        @sex.setter
        def sex(self,value):
            if not isinstance(value,str):      #如果性别不为字符串,就报错
                raise TypeError("性别必须为字符串")
            self.__sex = value
    
    p1 = People("egon",111)     #执行报错
    
    ----------------
    TypeError: 性别必须为字符串
    @property 修改
    # 实例化时,删除性别
    class People:
        def __init__(self,name,Sex):
            self.name = name
            self.sex = Sex      #此时是self.sex,而不是self.__sex
                            #实例化self.sex时候,会执行下面的@sex.setter内容
        @property
        def sex(self):
            return self.__sex
    
        @sex.setter
        def sex(self,value):
            if not isinstance(value,str):      #如果性别不为字符串,就报错
                raise TypeError("性别必须为字符串")
            self.__sex = value
    
        @sex.deleter
        def sex(self):
            del self.__sex
    
    p1 = People("egon","male")
    print(p1.sex)
        male
    del p1.sex          #删除
    print(p1.sex)
        报错
    @property 删除
  • 相关阅读:
    【slenium专题】Webdriver同步设置
    【Selenium专题】WebDriver启动firefox浏览器
    【Selenium专题】WebDriver启动Chrome浏览器(二)
    【Selenium专题】WebDriver启动Chrome浏览器(一)
    Jenkins邮件设置
    Jenkins安装笔记
    for循环输出i为同一值的问题,SetTimeOut
    const、let、var的区别
    浏览器title失去焦点时改变title
    clone对象或数组
  • 原文地址:https://www.cnblogs.com/golangav/p/6202974.html
Copyright © 2020-2023  润新知