一、面向对象编程
面向过程是一种以过程为中心的编程思想,它先是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,在使用时依次调用,是一种基础的顺序思维方式。面向过程的开发方式是对计算机底层结构的一种抽象,它将程序分为数据和操纵数据的操作两部分,其核心问题是数据结构和算法的开发和优化。常见支持面向过程的编程语言有C、COBOL等。
面向对象是按人们认识客观世界的系统思维方式,采用基于对象(实体)的概念建立模型,模拟客观世界分析、设计、实现软件的办法。面向对象方法把所有事物都当作独立的对象,处理问题的过程中所思考的关键不再是怎样用数据结构来描述问题,而是直接考虑重现问题中各个对象之间的关系。常见的支持面向对象的编程语言有C++、C#、Java等。
1、类和对象
Python是一种面向对象的编程语言,其一切对象都是对象。涉及面向对象的术语如下:
1)、类(Class): 用来描述具有相同属性和方法的对象集合,定义了该集合中每个对象所共有的属性和方法。类是生成对象的 “模板”。定义一个类的语法如下:
class 类名:
<数据成员声明1>
<数据成员声明2>
......
2)、对象:通过类定义的数据结构实列。对象由类变量、实列变量和方法构成。 3)、数据成员:类变量或者实例变量,用于处理类及其实例对象的相关数据,又称属性。
4)、类变量:同一个类的所有对象均可访问的变量。类变量在整个实例化的对象中是公用的,其定义在类中且在函数体之外。类变量一般不作为实例变量使用。调用时使用 类名点 的方式直接访问。
5)、实例变量:在类的声明中,属性使用变量来表示的。这种变量称为实例变量,是在类内部、类的其他成员方法之外声明的。仅供各个实例对象使用。
6)、方法:类中定义的函数。
7)、实例化:创建一个类的实例,即生成类的一个具体对象。可以访问类变量。
class Class1:
a = 10
# Python 中特殊的方法---魔术方法,其名称前后分别添加两个下划线,文章后面有相关说明
def __init__(self):
self.x = 5
self.y = 6
# 方法的定义
def add(self):
return self.x + self.y
c = Class1() # 实例化
print(c.add()) # 11
Class1.aa = 100 # 定义类变量
c.bb = 200 # 定义实例变量
print(Class1.aa, c.bb) # 100 200
c.dd = 300 # 定义实例变量,只能实例对象才可访问
c.ee = 400 # 定义实例变量
print(c.dd, c.ee) # 300 400
Class1.ff = 500 # 定义类变量,同一个类的所有对象都可访问
Class1.gg = 600 # 定义类变量,在整个实例化的对象中是公用的
print(Class1.ff, Class1.gg) # 500 600
d = Class1() # 实例化,生成类的一个具体对象
print(d.x, d.y) # 5 6 ,类的属性,可以访问
print(d.ff, d.gg) # 500 600 ,类变量,可以访问
print(d.dd, d.ee) # 报错:AttributeError: 'Class1' object has no attribute 'dd',dd/ee都是实例变量,不是这个实例声明的,不能访问
8)、继承:只一个派生类(子类,Derived Class)继承基类(父类,Base Class)的字段和方法。继承允许把一个派生类的对象作为一个基类对象对待。Python 支持多重继承 ,若是父类中有相同的方法名,而在子类中使用时未指定,Python 将按照从左至右的顺序在这些父类中查找该方法。
9)、方法的重写/方法的覆盖:在子类中定义与父类同名的方法。
class Animal:
name = ""
def Speak(self):
pass
# 子类继承父类,可以对父类的方法进行继承、重写或覆盖
class Cat(Animal):
name = '猫'
def Speak(self):
print("喵~")
class Human(Animal):
name = "人"
def Speak(self):
print("你好~")
# 多重继承
class Actor(Human, Cat):
name = "演员"
def Speak(self):
Human.Speak(self)
Cat.Speak(self)
c = Cat()
c.Speak() # 喵~
h = Human()
h.Speak() # 你好~
# 使用时未指定,按照从左至右的顺序到父类中查找
a = Actor()
a.Speak() # 你好~ 、喵~
1.1 类的属性和方法描述
与C++、C#、Java等语言相似,Python支持为类的属性和方法设置特定的访问权限,但不是通过关键字区分,而是使用一套约定式的规则。
1)、使用两个下划线 “__” 开头的属性或方法为私有(Private)的,不能再类的外部直接访问,在类内部以 “self.__属性名或方法名” 的方式使用。
2)、使用一个下划线 ”_“ 开头的属性或方法为保护(Protected)的,只能在类或子类中访问,在类内部以 ”self._属性名或方法名“ 的方式使用。
3)、其他的属性或方法为公有的(Public),可在类的外部直接访问,在类内部以 “self.属性名或方法名” 的方式使用。
class ClassMethod:
public1 = 10
_protected1 = 20
__private1 = 30
def publicFunc1(self):
print("公有方法1")
def _protectedFunc1(self):
print("保护方法1")
def __privateFunc1(self):
print("私有方法1")
class Class2(ClassMethod): # 继承
public2 = 100
_protected2 = 200
__private2 = 300
def publicFunc2(self):
print("公有方法2")
def _protectedFunc2(self):
print("保护方法2")
def __privateFunc2(self):
print("私有方法2")
cm = ClassMethod() # 实例化
print(cm.public1) # 10 ,公有属性,可在类的外部直接访问
print(cm._protected1) # 20 ,保护属性,可以在类和子类中访问
print(cm.__private1) # 触发了AttributeError异常,因为在外部直接访问类的私有属性__private1
cm.publicFunc1() # 公有方法1 ,公有方法可以在类的外部直接访问
cm._protectedFunc1() # 保护方法1 ,保护方法可以在类或子类中访问
cm.__privateFunc1() # 触发了AttributeError异常,因为在外部直接访问类的私有方法__privateFunc1()
c2 = Class2() # 实例化 继承了父类,可以访问父类的属性和方法
print(c2.public1) # 10 ,继承的父类,可以访问父类的公有属性
print(c2._protected1) # 20 ,继承的父类,可以访问父类的保护属性
print(c2.__private1) # 触发触发了AttributeError异常,因为在外部直接访问类的私有属性__private1
c2.publicFunc1() # 公有方法1 ,继承的父类,可以访问父类的公有方法
c2._protectedFunc1() # 保护方法1 ,继承的父类,可以访问父类的保护方法
c2.__privateFunc1() # 触发触发了AttributeError异常,因为在外部直接访问类的私有方法__privateFunc1
print(c2.public2) # 100
print(c2._protected2) # 200
print(c2.__private2) # 触发了AttributeError异常,因为在外部直接访问类的私有属性__private2
c2.publicFunc2() # 公有方法2
c2._protectedFunc2() # 私有方法2
c2.__privateFunc2() # 触发了AttributeError异常,因为在外部直接访问类的私有方法__privateFunc2
2、特殊的方法–魔术方法
Python 中一些特殊的方法,其名字前后分别添加了两个下划线,这些都称为 “魔术方法”。使用这些方法可以实现运算符重载,也可以将复杂的逻辑封装成简单的API。常用的魔术方法如下所示: 使用魔术方法,采用运算符重载的方式实现向量的加减法操作,如下:
class Vector:
a = None
b = None
# __init__ 对象初始化时调用,使用传入的参数初始化该实例
def __init__(self, a, b):
self.a = a
self.b = b
# __str__ 定义当前类的实例的文本显示内容
def __str__(self):
return '向量(%d, %d)'% (self.a, self.b)
# __add__ 实现操作符加法的作用
def __add__(self, other):
return Vector(self.a + other.a, self.b + other.b)
# __sub__ 实现操作符减法的作用
def __sub__(self, other):
return Vector(self.a - other.a, self.b - other.b)
v1 = Vector(1, 2) # 这里传入的参数初始化了改实例
v2 = Vector(3, 4)
v3 = Vector(5, 6)
print(v1, "+", v2, "=", v1+v2) # 向量(1, 2) + 向量(3, 4) = 向量(4, 6)
print(v1, '-', v2, '=', v1-v2) # 向量(1, 2) - 向量(3, 4) = 向量(-2, -2)
print(v1, '+', v2, '+', v3, '=', v1 + v2 + v3) # 向量(1, 2) + 向量(3, 4) + 向量(5, 6) = 向量(9, 12)
二、文件操作
文件的操作主要分为读取和写入。 1)、读取文件是指将磁盘上的文件内容读入内存或命名管道。 2)、写入文件是指将内存、缓冲区或命名管道内的内容写入磁盘上的指定文件。
Python 中操作文件也有两种常用的方法: 1)、使用内置支持的 file 对象完成大部分文件操作; 2)、使用 os 模块提供的更为丰富的函数完成对文件和目录的操作。
但是在读取或写入文件之前,必须使用内置函数 open() 打开文件,语法如下:
file object = open(filename[, accessmode="r"][, buffering="-1"][, encoding=None][, errors=None][, newline=None][, closefd=True][, opener=None])
通常,文件以文本模式被打开,这意味着向文件写入或读出的字符串会被以特定的编码方式编码(默认是 UTF-8)。 以二进制模式打开文件表示数据会以字节对象的形式读出或写入,这种模式应该用于存储非文本内容的文件。 在文本模式下,读取时会默认将平台有关的行结束符转换为 \n (UNIX用 \n,Windows用 \r\n);在文本模式下写入时会默认将出现的 \n 转换成平台有关的行结束符。
因此对不同类型的文件要采用正确的模式读写。 1)、open() 函数的 accessmode 参数 2)、open() 函数的 errors 参数可取值
if __name__ == '__main__':
# 打开文件,以读写的方式打开文件,如文件不存在则创建新文件,若存在则覆盖该文件
f = open('text.txt', 'w+')
# 获取文件描述符
print(f.fileno())
# 写入文本
f.write("Python用语言简单易学。\n是的,还非常好用和使用\n")
# 关闭文件
f.close()
# 以只读方式打开文件,并指向文件头
f = open('text.txt', 'r')
# 读取文件内容并输出至终端屏幕
print(f.read())
# 关闭文件
f.close()
# 以追加、读写的方式打开文件
f = open('text.txt', 'a+')
f.write('追加一个字段\n') # 追加写入内容,结果是在文件中,新写入了 ”追加一个字段“ 。
f.close()
小案例:输出斐波那契数列的第 n 个数,例如 n = 50
if __name__ == '__main__':
k = {0:0, 1:1}
def Fibonacci(n):
if n in k:
return k[n]
res = Fibonacci(n - 1) + Fibonacci(n - 2)
k[n] = res
return res
print('Fibonacci(%d) = %d' % (50, Fibonacci(50)))
# Fibonacci(50) = 12586269025 = Fibonacci(49) + Fibonacci(48)
# Fibonacci(1) = 1 = Fibonacci(0) + Fibonacci(-1)
# Fibonacci(2) = 1 = Fibonacci(1) + Fibonacci(0)
# Fibonacci(3) = 2 = Fibonacci(2) + Fibonacci(1)
# Fibonacci(4) = 3 = Fibonacci(3) + Fibonacci(2)
|