Python面向对象编程(Object Oriented Pro

2021-04-20  本文已影响0人  八步里
面向对象编程

面向过程编程和对象编程都是程序设计思想,面向过程程序设计是将需要实现的功能流程化列出来,让程序依次按照命令执行。跟面向过程程序设计不同,面向对象编程是将现实中的个体的状态和行为抽象化成对象的属性和方法,通过对象间的方法进行信息处理和通信模拟现实世界中的实体交互,高度抽象的设计思想可以模拟现实中的情景和需求,更方便地面对大型程序设计的需要。
Python是一门面向对象编程的语言,其将所有的数据类型都视为对象。其中最重要的概念是类和实例。类是为某一个现实对象创建出的模板,其包含了该对象所拥有的属性和方法,通过实例化对类进行个性化设定便创造出实例。

1.Class 和 Instance

类是作为对象的模板,可以在里面设定公共属性(类属性)、实例属性(对象属性)、构造器和方法

class Dog(object):
    #类属性默认用大写命名
    CATEGORY = '犬属'
    #构造器由__init__命名,括号内包括固定参数self和实例属性
    def __init__(self,name,ages):
        self.name = name
        self.__ages = ages
    #方法的括号第一个参数一定是self,可加其他参数
    def run(self,state):
        print("狗儿跑得"+state+",我叫"+self.name)
    #将属性复制功能封装在函数中提供了一定的安全性,并且可以在赋值中添加校准及其他功能。
    def setAges(self,ages):
        if type(ages) == int:
            self.__ages = ages
        else:
            print("你输入的不是数字,不能充当年龄")
    def getAges(self):
        return self.__ages
    
dog = Dog("旺财",12)
print(dog.CATEGORY)
dog.run("慢")
dog.setAges(10)
print(dog.getAges())

结果为:

>犬属
>狗儿跑得慢,我叫旺财
>10

在上面的实例属性设定中出现了__ages这样子以双下划线开头的属性定义,这标志着是private变量,不准许通过实例.变量的方式来读取,这种保护机制便确保了外部程序没办法随意修改对象内部的状态。其实本质上解释器会将该变量名转化为_Dog__ages在其前面添加上_类名

dog.__ages = 1
# 仅仅是为实例创建了一个新的属性而已,动态语言确实可以运行时添加属性
print(dog.getAges())
print(dog.__ages)
# __ages在实例化时已经变成了_Dog__ages
dog._Dog__ages = 13
print(dog.getAges())

结果是:

>10
>1
>13

注意:有些时候在类定义中出现了了一个下划线开的实例变量名,这样的实例变量在程序层面上是可以正常访问的,但是按照约定俗成的规定,这种命名形式是告诉使用者将其看成私有变量,不要从外面进行访问。

2.类属性和实例属性

类属性是指该变量归类所有,所有新创建的实例都可以访问得到,但只能通过类名索引的方式来修改勒边来那个。Python可以在类定义中用self定义实例变量,作为动态语言也可以在程序执行过程中通过实例直接创建实例变量。

>>> class Dog():
    name = "旺财"

>>> dog = Dog()
# 访问类变量
>>> dog.name
'旺财'
# 绑定新的实例属性
>>> dog.ages = 12
>>> dog.ages
12
# 实例属性覆盖类属性
>>> dog.name = "耿狗"
>>> dog.name
'耿狗'
# 删除实例属性,重新可以访问类属性
>>> del dog.name
>>> dog.name
'旺财'
# 重新定义类属性
>>> Dog.name = "lal"
>>> Dog.name
'lal'
# 测试是不是真正删除类属性
>>> del Dog.name
>>> Dog.name
Traceback (most recent call last):
  File "<pyshell#23>", line 1, in <module>
    Dog.name
AttributeError: type object 'Dog' has no attribute 'name'

python作为动态语言可以在运行过程中为实例绑定新的实例属性(对类和对其他实例无效),如上面所示为Dog实例dog绑定了新的实例属性ages。有时候我们可能希望限制绑定的属性,python提供了slots特殊类属性来限定可动态绑定的实例属性,在类定义的时候将可能需要动态绑定的实例属性名创建成一个元组赋给slots类属性,绑定除了指定属性外的实例属性将会出现错误。

class Dog(object):
    __slots__ = ('name','ages')

dog = Dog()
dog.color = yellow

结果为:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Dog' object has no attribute 'color'

3.枚举类与元类

在python中可以用大写字母来设定常量,表明不可修改,但是这并不是一种语言机制而是一种自觉机制,有被篡改的风险。在python3.4中添加了枚举类便于大小一定的特殊类的定义,如季节、工作日等。
枚举类有两种不同的设定形式,一种便是按照类定义的形式继承Enum类,可以在类中自定义的设定每一个成员的具体值,或者可以用Enum函数直接对每一个成员自动编排值。

from enum import Enum,unique

# 用@unique使枚举类成员的值都是唯一的
@unique
class Season(Enum):
    spring = 1
    sunner = 2
    autumn = 3
    winter = 4
# 可以用Eunm函数直接定义
Season = Enum('Season',('spring','sunner','autumn','winter'))

其中以枚举类名.成员名的形式来索引每一个成员,每一个成员都有其名字和值,可以调用枚举类内部的members变量来获取包含全部成员情况的字典

spring = Season.spring
print(spring.name)
print(spring.value)
for name, member in Season.__members__.items():
    print(name, '=>', member, ',', member.value)

输出:

>spring
>1
>Season.sunner
>spring => Season.spring , 1
>sunner => Season.sunner , 2
>autumn => Season.autumn , 3
>winter => Season.winter , 4
>Season.spring
>Season.sunner
>Season.autumn
>Season.winter

4.继承与多态

上面举的例子Dog类继承了object类,故object称为Dog类的Super class,Dog类为Subclass,子类通过继承获得了父类的全部成分,并且拥有重新复写成分的能力。

class WangCai(Dog):
    def __init__(self,state,name,ages):
        self.state = state
        self.name = name
        self.ages = ages
    def run(self):
        print("我是子类的旺财")
        super().run(self.state)

wangcai = WangCai("慢","旺财",12)
wangcai.run()

结果为:

>我是子类的旺财
>狗儿跑得慢,我叫旺财

多态一般是指在静态类型语言中的子类可以传入需要父类做参数的函数,在运行的时候调用子类的相关内容,包含了编译时类型和运行时类型的概念。这样一来原先为父类编写的方法也可以操作子类,而不需要从新定义新的函数,大大降低了开发成本。但是其实像python这种动态类型的语言,设定的参数并不需要提前设定类型,参数引用的对象是具体运行到的时候才定义的,因此在实际操作时可以灵活很多。只要满足函数中所需的调用的成分,就可以充当参数传入并在函数内部进行调用。这就是动态语言的“鸭子类型”,它并不要求严格的继承体系,一个对象只要“看起来像鸭子,走起路来像鸭子”,那它就可以被看做是鸭子。

上一篇下一篇

猜你喜欢

热点阅读