[Python] 入门(10):Python 基础 -- 面向对象编程

往期回顾:

  • [Python] 入门(1):安装 Python 及必要组件
  • [Python] 入门(2):Python 基础 – 变量
  • [Python] 入门(3):Python 基础 – 内建函数
  • [Python] 入门(4):Python 基础 – 列表和词典的方法
  • [Python] 入门(5):Python 基础 – 字符串的方法
  • [Python] 入门(6):Python 基础 – Python 基础 – 循环,条件和迭代器
  • [Python] 入门(7):Python 基础 – 自定义函数
  • [Python] 入门(8):Python 基础 – 解析式,生成器和程序错误
  • [Python] 入门(9):Python 基础 – 字符串格式化
  • [Python] 入门(10):Python 基础 – 面向对象编程(本文)

本文目录


Wikipedia 说:

面向对象程序设计(英语:Object-oriented programming,缩写:OOP)是种具有对象概念的程序编程典范,同时也是一种程序开发的抽象方针。它可能包含数据、属性、代码与方法。对象则指的是类的实例。它将对象作为程序的基本单元,将程序和数据封装其中…面向对象程序设计中的每一个对象都应该能够接受数据、处理数据并将数据传达给其它对象,因此它们都可以被看作一个小型的“机器”,即对象。

打个比方,“类”是做汤圆的共同特征,“对象”是已经做好的汤圆。不管汤圆是五仁馅还是芝麻馅,它们都有共同的特征:外面用糯米粉包裹,里面有馅…如果我们把所有汤圆的共同特征都提取出来,这些特征就是类。在开始讨论类以前,我们先了解个概念:

命名空间

命名空间(namespace)是一个从名字到对象的映射。举个例子,假如定义一个函数 sum,那么 sum 就是对应函数的命名空间。这么说可能不好理解,我们来看一个例子:

>>> a = 1
>>> b = 2

>>> def names():
...     a = 4
...     print("在这个命名空间里 a 的值是:", a)
...     global b 
...     b = 5
...     print("在这个命名空间里 b 的值是:", b)
    
>>> print("在全局命名空间里,a 的值是:", a)
在全局命名空间里,a 的值是: 1
>>> print("在全局命名空间里,b 的值是:", b)
在全局命名空间里,b 的值是: 2
>>> names()
在这个命名空间里 a 的值是: 4
在这个命名空间里 b 的值是: 5
>>> print("现在在全局命名空间里,a 的值是:", a)
现在在全局命名空间里,a 的值是: 1
>>> print("现在在全局命名空间里,b 的值是:", b)
现在在全局命名空间里,b 的值是: 5

解释一下发生了什么:首先,我们在全局命名空间里定义了 a = 1,b =2;然后我们在函数 names 的局部命名空间里重新定义了 a = 3,b = 4,之后分别打印在不同命名空间里的 a 和 b。

我们先来看 a。a 在 names 里被放在了局部命名空间里(这叫做局部赋值),在 names 外被放在了全局命名空间里,两个命名空间互不影响,所以在 names 里面打印出 1,在 names 外面打印出 4。

b 就有点复杂了。我们在 names 加了一个 global 语句,强制 b 被放在全局命名空间里(这叫做全局赋值),这样 names 里的 b 和 names 外的 b 处在同一个命名空间,所以在调用 names 以后,全局命名空间里 b 的值就被覆盖了,所以开始 b 的值是 2,调用函数后再打印,无论在函数的内外打印,b 的值都变成了 5。

默认情况下,在函数里的变量都是局部赋值。

定义一个类很简单:

>>> class ClassName:
... <statement-1>
... .
... .
... .
... <statement-N>

类对象

类对象有两种操作:属性引用和实例化。

属性引用

属性引用使用标准语法 obj.attr。比如我们定义一个类:

>>> class avengers:
...     '''复仇者联盟'''
...     name = "Iron Man"
...     
...     def say():
...         print("I'm Iron Man!")
>>> print(avengers.name)
Iron Man
>>> avengers.say()
I'm Iron Man!

name 变量成了 avengers 的属性(没有括号),say 函数成了 avengers 的方法(有括号)。

实例化

可以想象成用汤圆机器做了一个汤圆,方法是调用这个类:

avenger = avengers()

如果想创建一个带有特定初始状态的函数,需要在类中包含一个特殊的 __init__()(一边各有两个下划线)的方法:

>>> class avengers:
...     '''复仇者联盟'''
...     def _init_(self, a, b):
...         self.name = a
...         self.age = b

想在这个类里填充数据并调用也非常简单:

>>> x = avengers("Captian America", 101)
>>> x.name, x.age
('Captian America', 101)

以上都是非常简单的示例,现在来个复杂一点的(就复杂那么一点而已):

>>> class avengers:
...     '''复仇者联盟'''
...     alias = []
...     def __init__(self, a):
...         self.name = a
...        
...     def add_alias(self, name):
...        self.alias.append(name)
        
>>> Thor = avengers("Thor")
>>> Thor.add_alias("Son of Odin")
>>> Thor.add_alias("God of Thunder")
>>> Thor.alias
['Son of Odin', 'God of Thunder']

我们先定义了索尔的类,然后分别将他的昵称以方法的形式加在类中,最后以属性的方式调用他的昵称。看起来挺好的,那我们在这个基础上再做一个鹰眼的类:

>>> Barton = avengers("Barton")
>>> Barton.add_alias("Hawkeye")
>>> Barton.add_alias("Arrow Guy")
>>> Barton.alias
['Son of Odin', 'God of Thunder', 'Hawkeye', 'Arrow Guy']

哎不对,鹰眼的昵称怎么还有索尔的?其实是上面定义的类的第三行 alias = [] 位置不对,它被定义成了类里的全局变量,应该放到 __init__(self, a) 里成为局部变量。改一下,再试一次:

>>> class avengers:
...     '''复仇者联盟'''
...     def __init__(self, a):
...         self.name = a
...         self.alias = []
...     def add_alias(self, name):
...         self.alias.append(name)
        
>>> Thor = avengers("Thor")
>>> Thor.add_alias("Son of Odin")
>>> Thor.add_alias("God of Thunder")
>>> Thor.alias
['Son of Odin', 'God of Thunder']
>>> Barton = avengers("Barton")
>>> Barton.add_alias("Hawkeye")
>>> Barton.add_alias("Arrow Guy")
>>> Barton.alias
['Hawkeye', 'Arrow Guy']

这回就对了嘛!

类里还可以加循环和判断、解析式和生成式等等,因为这是入门文章,所以就不说了。学无止境啊~现在 Python 基础知识就正式完成了,下一篇开始会讲各种常用模块,包括内建模块,numpy,pandas 和 matplotlib。


练习(写出生成如下变量的代码或结果):
定义一个叫做 fruit 的类,接受“水果名字”和“水果数量”两个变量。同时放置一个判断,当水果数量小于 5 时,打印“**水果只有**个”;当水果数量多于 5 时,打印“**水果有**个”。示例:

>>> a = fruit("apple", 3)
>>> ... # 自选变量名称
apple only have 3
>>> b = fruit("banana", 6)
>>> ... # 自选变量名称
banana have 6

答案下篇文章公布。欢迎把答案留言与老宅交流、互动!


上一篇练习的答案:

# 1. '  1.58000000  ' (前后各两个空格);
>>> f"{1.58:^14.8f}"
'  1.58000000  '
# 2. 你现在的时间,格式为 “月/日/四位年 缩写星期几 小时(24 小时制)-分钟-秒”。
>>> import datetime
>>> f"{datetime.datetime.now():%m/%d/%Y (%a) %H-%M-%S}"
'05/31/2019 (Fri) 16-53-45'
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值