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__
原文地址:https://www.cnblogs.com/czalinux/p/6675641.html