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__
    
  • 相关阅读:
    Linux之文件处理命令
    Linux基础命令
    rip实验
    Linux基础之磁盘分区
    mysql安装
    centos Apache、php、mysql默认安装路径
    You probably tried to upload too large file. Please refer to documentation for ways to workaround this limit.
    Wrong permissions on configuration file, should not be world writable!
    机器会学习么 学习总结
    实验 5 Spark SQL 编程初级实践
  • 原文地址:https://www.cnblogs.com/czalinux/p/6675641.html
Copyright © 2011-2022 走看看