zoukankan      html  css  js  c++  java
  • Python 面向对象进阶

    面向对象基础知识回顾

    • 面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 的使用
    • 类 是一个模板,模板中包装了多个“函数”供使用(可以讲多函数中公用的变量封装到对象中)
    • 对象,根据模板创建的实例(即:对象),实例用于调用被包装在类中的函数
    • 面向对象三大特性:封装、继承和多态

    类的成员

    类的成员可以分为3类:

    • 字段(属性)
    • 方法
    • 熟悉

    Alt text
    注意:在所有成员中,只有普通字段(属性)的内容存在对象中,即:根据此类创建了多少对象,在内存中就有多少个普通字段。而其他成员,则都是保存在类中,即:无论对象的多少,在内存中只创建一份

    一、字段(属性)

    字段包括:普通字段(属性)和静态字段(属性),他们在定义和使用中都有所区别,而本质的区别是内存中保存的位置不同。

    • 普通字段属于对象

    • 静态对象属于类

        class Province(object):
        
            #静态字段(属性)
            country = 'China'
            def __init(self,name):
                #普通字段
                self.name = name
        #调用普通字段(属性)    
        obj = Province('Gansu')
        print(obj)
        #直接调用静态字段(属性)
        Province.country
      

    静态字段在内存中保存一份

    普通字段在每个对象中都保存
    应用场景:通过类创建对象时,如果每个对象都具有相同的字段(属性),即可使用静态字段


    二、方法

    方法包括:普通方法、静态方法、属性方法三种,三种在内存中都归属类,区别在于调用方式不同。

    • 普通方法:由对象调用;至少一个self参数;执行普通方法时,自动将调用该方法的对象赋值给self;

    • 类方法:由类调用;至少一个cls参数;执行类方法时,自动将调用该方法的类复制给cls;

    • 静态方法:由类调用;无默认参数;

        class People(object):
            def __init__(self,name):
                self.name = name
      
           def Hello(self):
                ''' 定义普通方法,至少有一个self参数 '''
                print('Hello,I am %s'%self.name)
                print('普通方法')
      
            @classnethod
            def class_func(cls):
                """ 定义类方法,至少有一个cls参数 """
      
                print ('类方法')
      
            @staticmethod
            def static_func():
            	""" 定义静态方法 ,无默认参数"""
      
                print ('静态方法')
        #调用普通方法
        p = People('miao')
        p.Hello()
      
        #调用类方法
        People.class_func()
      
        #调用静态方法
        People.static_func()
      

    三、属性

    Python中的属性其实是普通方法的变种。

    1.属性的基本使用

    # ############### 定义 ###############
    class Foo:
    
        def func(self):
            pass
    
        # 定义属性
        @property
        def prop(self):
            pass
    # ############### 调用 ###############
    foo_obj = Foo()
    
    foo_obj.func()
    foo_obj.prop   #调用属性
    

    由属性的定义和调用要注意一下几点:

    • 定义时,在普通方法的基础上添加 @property 装饰器;
    • 定义时,属性仅有一个self参数
    • 调用时,无需括号
      方法:foo_obj.func()
      属性:foo_obj.prop

    注意:属性存在意义是:访问属性时可以制造出和访问字段完全相同的假象

    示例

            class Pager:
    
                def __init__(self, current_page):
                # 用户当前请求的页码(第一页、第二页...)
                self.current_page = current_page
                # 每页默认显示10条数据
                 self.per_items = 10
                @property
                def start(self):
                val = (self.current_page - 1) * self.per_items
                return val
                @property
                def end(self):
                val = self.current_page * self.per_items
                return val
    
            # ############### 调用 ###############
    
            p = Pager(1)
            p.start #就是起始值,即:m
            p.end   #就是结束值,即:n
    

    2.属性的两种定义方式

    属性的定义方式有两种:
    * 装饰器: 即:在方法上应用装饰器
    * 静态字段 即:在累中定义值为property对象的静态字段

    装饰器的方式:在类的普通方法上应用@property装饰器

    我们所知道python的类中有经典类和新式类

    经典类

    
    # ############### 定义 ###############    
    class Goods:
    
        @property
        def thing(self):
            return "miao~"
    # ############### 调用 ###############
    obj = Goods()
    result = obj.thing  # 自动执行 @property 修饰的 thing 方法,并获取方法的返回值
    

    新式类,具有3中@property装饰器

    # ############### 定义 ###############
    class Goods(object):
    
        @property
        def price(self):
            print '@property'
    
        @price.setter
        def price(self, value):
            print '@price.setter'
    
        @price.deleter
        def price(self):
            print '@price.deleter'
    
    # ############### 调用 ###############
    obj = Goods()
    
    obj.price          # 自动执行 @property 修饰的 price 方法,并获取方法的返回值
    
    obj.price = 123    # 自动执行 @price.setter 修饰的 price 方法,并将  123 赋值给方法的参数
    
    del obj.price      # 自动执行 @price.deleter 修饰的 price 方法
    

    注:经典类中的属性只有一种访问方式,其对应的@property修饰方法
    新式类中的属性有三种访问方式,并分别对应了3个@property、@方法吗.setter、@方法名.deleter修饰的方法
    由于新式类中具有三种访问方式,我们可以根据他们几个属性的访问特点,分别将三个方法定义为对同一个属性:获取、修改、删除

    新式类示例:

    class Goods(object):
    
        def __init__(self):
            # 原价
            self.original_price = 100
            # 折扣
            self.discount = 0.8
    
        @property
        def price(self):
            # 实际价格 = 原价 * 折扣
            new_price = self.original_price * self.discount
            return new_price
    
        @price.setter
        def price(self, value):
            self.original_price = value
    
        @price.deltter
        def price(self, value):
            del self.original_price
    
    obj = Goods()
    obj.price         # 获取商品价格
    obj.price = 200   # 修改商品原价
    del obj.price     # 删除商品原价
    复制代码
    

    静态字段方式,创建值为property对象的静态字段

    当使用静态字段的方式创建属性时,经典类和新式类无区别

    class Foo():
    	def get_bar(self):
    		return('miao')
    
    	BAR = property(get_bar)
    
    obj = Foo()
    result = obj.BAR
    print(result)
    

    类成员的修饰符

    对于每一个类的成员而言有两种形式:

    • 公有成员
    • 私有成员

    公有成员和私有成员的定义不同
    私有成员命名时,前两个字符是下划线。(特殊成员除外,例如:init,call,__dict__等)

    class C(object):
        def __init__(self):
            self.name = '公有字段'
            self.__foo = '私有字段'
            
    

    私有成员和公有成员的访问限制不同:

    静态字段

    • 公有静态字段:类可以访问;类内部可以访问;派生类中可以访问
    • 私有静态字段:仅类内部可以访问
    公有静态字段
    class School(object):
    	addr  = 'Beijing,公有静态字段'
    	def func(self):
    		print(School.addr)
    class Student(School):
    	def show(self):
    		print(School.addr)
    
    School.addr     #类访问
    obj = School()  #实例化
    obj.func()      #类内部可以访问
    
    obj_son = Student() #实例化子类
    obj_son.show()	    #子类[派生类]中可以访问
    
    私有静态字段
    class School(object):
    	__addr  = 'Beijing,公有静态字段'
    	def func(self):
    		print(School.__addr)
    class Student(School):
    	def show(self):
    		print(School.__addr)
    
    School.__addr     #类访问 	   ==> Flase
    obj = School()  #实例化
    obj.func()      #类内部可以访问 	==>True
     
    obj_son = Student() #实例化子类
    obj_son.show()	    #子类[派生类]中可以访问   ==>Flase
    

    普通字段

    • 公有普通字段:对象可以访问;类内部可以访问;派生类中可以访问
    • 私有普通字段:仅类内部可以访问
      ps:如果想要强制访问私有字段,可以通过[对象._类名__私有字段名]访问【如:obj._C__foo】,不过不建议访问私有成员。
    公有普通字段
    class School(object):
    	def __init__(self):
    		self.addr = 'Beijing,公有字段'
        
    	def func(self):
    		print(self.addr)  # 类内部访问
    
    class Student(School):
    	def show(self):
    		print(self.addr)  # 派生类中访问
    
    obj = Schoo()
    
    obj.addr    # 通过对象访问
    obj.func()  # 类内部访问
    
    obj_son = Student()
    obj_son.show() #派生类中访问   
    
    
    私有普通字段
    class School(object):
    	def __init__(self):
    		self._addr = 'Beijing,公有字段'
        
    	def func(self):
    		print(self.__addr)  # 类内部访问
    
    class Student(School):
    	def show(self):
    		print(self.__addr)  # 派生类中访问
    
    obj = Schoo()
    
    obj.__addr    # 通过对象访问   ==> Flase
    obj.func()  # 类内部访问       ==> True
    
    obj_son = Student()         
    obj_son.show() #派生类中访问   ==> Flase
    
    

    方法、属性的访问方法与上述类似,即:私有成员只能在类内部使用

    类的特殊成员

    1. doc

    表示类的描述信息

    class Foo(object):
    	'''Hello 这是类的描述信息'''
    	def func(self):
    		pass
    print(Foo.__doc__)
    

    2. moudleclass

    moudle 表示当前操作的对象在哪个模块
    class 表示当前操作的类是什么

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    
    class C(object):
    
        def __init__(self):
    	    self.name = 'miao'
    from lib.aa import C
    obj = C()
    print (obj.__module__)  # 输出 lib.aa,即:输出模块
    print (obj.__class__)      # 输出 lib.aa.C,即:输出类
    

    3. init

    构造方法,通过类创建对象时,自动触发执行

    class Foo(object):
    	def __init__(self,name):
    		self.name = name
    		print(name)
    obj = Foo('miao')   #自动执行类中__init__方法
    

    4. del

    析构方法,当对象在内存中释放时,自动触发执行
    注:此方法一般无需定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行的,所以,析构函数是调用解释器在进行垃圾回收时自动触发执行的

    class Foo(object):
    	def __del__():
    		pass
    
    

    5. call

    对象后面加括号,触发执行
    注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 call 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()

    class Foo(object):
        def __init__(self):
            print('This is __init__')
    
        def __call__(self, *args, **kwargs):
            print('This is __call__')
    
    obj = Foo()   #触发__init__
    obj()         #触发__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 'miao'
    
    
    obj = Foo()
    print (obj)
    # 输出:miao  没有定义__str__的时候输出内存地址
    

    8. getitemsetitemdelitem

    用于索引操作,如字典。以上分别表示获取、设置、删除数据

    #!/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'] = 'wupeiqi'   # 自动触发执行 __setitem__
    del obj['k1']           # 自动触发执行 __delitem__
    
    

    9. getslicesetslicedelslice

    该三个方法用于分片操作,如:列表

    #!/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__
    
  • 相关阅读:
    CSS盒子模型
    Git
    FFmpeg
    根据经纬度查询当前地点,百度google接口
    取数组中随机元素
    PHP获取当前页面url
    冒泡
    PHP5中使用PDO连接数据库的方法
    js循环遍历
    判断网页中英文
  • 原文地址:https://www.cnblogs.com/czalinux/p/6675641.html
Copyright © 2011-2022 走看看