欢迎光临
生活尽了力,其他靠佛系

【Python】面向对象

面向对象编程一直是当前编程主流语言,特别是开发大型项目时,基本上都会选择使用。对于什么是面向对象,这里就不再介绍。而进行面向对象编程的第一步当然时创建一个类,类使得程序设计更加抽象,通过类的继承(Inheritance)组合(Composition)使得程序语言更接近人类的语言。

1 __init__方法

假如我们有一个类,如下:

class Test:
    def setName(self, name):
        self.name = name
    def getName(self):
        return self.name
    def getInfo(self):
        return self

这个类中有三个方法。进入类定义以后,会创建出一个新的局部作用域,我们待会去创建类的数据属性,而数据属性以及方法都是作用域此作用域的。类中self就代表当前类。
__init__方法用于初始化类的实例对象,如果了解过其它面向对象语言,如Java、C++,则可理解为是一个构造函数,但是在Python中执行__init__方法的时候,对象实例其实已经构造出来了,但该方法会在对象构造出来后自动执行,所以可以用于初始化我们所需要的数据属性。我们在上面的代码的基础上进行完善,有:

class Test:
    def __init__(self, name, gender, level):
        self.type = ('fire', None)
        self.gender = gender
        self.name = name
        self.level = level
    def setName(self, name):
        self.name = name
    def getName(self):
        return self.name
    def getGender(self):
        return self.gender
    def getLevel(self):
        return self.level
    def getInfo(self):
        return self

2.对象中的方法

2.1 方法引用

我们在定义类的方法时,程序并不会为我们的类分配内存,而在创建具体实例对象的程序才会为对象的每个数据属性和方法分配内存。对象中的方法和普通方法不同之处在于,第一个参数需要self参数,以表示当前对象,这个我们就可以通过对象去使用一个方法了。例如:

class testObj:
    def test(self):
        print("testObj对象的test方法运行了")

# 使用对象中的方法
testObj().test()
# 或者
test = testObj()
test.test()
# 结果
# testObj对象的test方法运行了
# testObj对象的test方法运行了

2.2 私有化

面向对象语言的特征是:封装、继承、多态。对于一个对象进行封装是很重要的,很多对象中的属性不需要、也不能随便被外部去访问,这时我们可以将这个属性私有化,这也是类的封装原则,然后使用get,set相关方法去获取和改变相关属性。
在Python中将类中属性进行私有化的方式是:只需在属性名前加上双下划线。例如:

class testObj:
    def __init__(self):
        self.__first = "first"
        self.__second = "second"
    def test(self):
        print("testObj对象的test方法运行了")
    def setFirst(self, first):
        self.__first = first
    def getFirst(self):
        return self.__first

test = testObj()
# get方法获取内部属性
print(test.getFirst())
# 直接访问内部属性
print(test.__first)

结果是在直接访问内部属性时出错,如下:

AttributeError: 'testObj' object has no attribute '__first'

2.3 迭代器

我们之前接触到Python容器对象(你可以理解为还能存放数据的数据类型)都可以使用for进行遍历。for语句实际上调用了iter(),而iter()函数会返回一个定义了next()方法的迭代器对象,它将在容器中逐一访问元素,当容器遍历完毕,next()找不到后续元素时,next()会引发一个StopIteration的异常,告知for循环终止。可能你现在还不理解什么叫迭代器,看看下面的示例,你就会理解了。

List = [1, 2, 4]
it = iter(List)    # 将List可迭代对象放入迭代器,得到一个迭代器对象
# 通过next()函数获取迭代器(一个可以按照对象内容返回值的容器)中的值
List = [1, 2, 4]
it = iter(List)    # 将List可迭代对象放入迭代器,得到一个迭代器对象
# 通过next()函数获取迭代器(一个可以按照对象内容返回值的容器)中的值
print(next(it))
print(next(it))
print(next(it))
# 每次可返回一个值,你也可以理解为:在创建一个迭代器时,有一个指针指向List中第一个元素,然后next()函数调用一次,就返回当前指针指向的内容,然后指针下移
print(next(it))  # 这是最后一个值了,如果再调用next()函数,则会报异常

了解了迭代器后面运行的原理,我们可以在类中书写自己的迭代器了。以下代码是生成一个[a,b]范围数字的迭代器。

class Series(object):
 def __init__(self, low, high):
  self.current = low
  self.high = high
 def __iter__(self):
  return self
 def __next__(self):
  if self.current > self.high:
   raise StopIteration
  else:
   self.current += 1
   return self.current - 1
n_list = Series(1,10)
print(list(n_list))
# 结果
# [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

其中有一个raise关键字,这是抛出异常的操作,具体可查看文献1,Python中的异常操作。

2.4 继承

继承的类容还是相对较多的,这里我们暂时简要描述一下。
继承是面向对象中非常重要的内容,也为代码重用带来了巨大的便利。继承是两个类或及其以上之间的父子关系,父类我们有时也称为基类,子类继承了基类所有的公有数据(并不是所有的数据都能继承下来)和方法,并且可以通过编写子类的代码再扩充自己的功能。
当然,在书写程序的时候,我们也不可能那么随机地继承,既然继承了,那么双方必然有一定的关系,可以从一个抽象类别逐渐到具体。举个例子:哺乳动物->狗->警犬,这是可以的,警犬继承了狗类(既然是警犬,那肯定具有够的基本属性了),狗继承哺乳动物,当然你可能想到宠物狗,宠物狗也是狗类,需要继承,但是又有别于警犬,那么这就是警犬这一级(这一代)的不同种类了。不过继承也会有一定的弊端,可能基类对于子类也有一定特殊的地方,例如某种类别的狗不具有绝大多数狗的行为或属性,在设计基类时就需要特别注意了。还有一点的就是,如果继承链太长了,任何一点的变化就会引起一连串的变化。
继承的语法:class 子类名(基类1,基类2,…),也就是说,在Python中,继承是支持多继承的。继承具有的特点如下:
– 在继承中基类初始化方法__init__不会被自动调用,如果子类希望调用基类的__init__方法,需要在子类的__init__中进行显示调用,这与Java、C++等区别还是挺大的。
– 在调用基类的方法时,需要加上基类的类名前缀,且带上self参数变量。注:在类中调用该类中定义的方法时不需要self参数。
– Python总时首先查找对应类的方法,也就是Python先查找当前类有没有对应方法,如果没有的话,再从父类中按顺序查找(一级一级的基类查找,就近原则)
– 子类不能访问基类的私有成员

这部分程序实例可参考文献2,这里就不展开介绍了。

Reference

1.https://www.runoob.com/python3/python3-errors-execptions.html
2.https://www.runoob.com/python3/python3-class.html

赞(0) 打赏
未经允许不得转载:AIAS编程有道 | Artificial Intelligence Algorithm Scientist » 【Python】面向对象
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!

 

觉得文章有用,就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏