终于,学习笔记系列文章与你见面了。作为一个小站全新的非原创系列,我将尝试着探索目前人工智能的创造潜力上限,并在成文的过程中尽可能多地使用生成式人工智能(AIGC)技术。
本次「Python学习笔记」系列文章,全程仅使用了一段 103 字的用户提示词,其余内容均由 OpenAI 的 GPT-3.5 模型生成。
在成文过程中,我使用了独立开发者「方糖」开发的 DeepGPT 程序,这是一个使用 AgentGPT 的提示词在纯前端进行任务分拆和结果输出的程序。
最终,GPT-3.5 模型所创作的内容多达 29536 字,我使用半小时左右的时间进行了文字排版,以使内容符合一个小站的 排版规范 。同时,为了阅读方便,全文将分拆为若干章节发出。
当然,Python 也是我即将在大学学习的内容之一。在日后的学习中,我会根据实际需要对内容进行补充或者简单修改。
由于当前 AIGC 生成的内容的版权归属尚不明朗,本文不加「原创」标签。
探讨Python面向对象编程
面向对象编程(OOP)是一种基于对象进行编程的方法,Python是一门支持OOP的语言。在Python中,对象是具有属性和方法的实体,属性是对象的状态,而方法是对象的行为。面向对象编程的核心要素是封装、继承和多态。
类和对象
在Python中,可以使用class
关键字来定义类,类是一种具有共同属性和方法的对象的集合。类中的方法可以访问类的属性和方法。类的实例化可以创建对象,对象是类中的具体实例。对象可以访问类中定义的属性和方法。
以下是一个简单的类的例子:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def say_hello(self):
print("Hello, my name is", self.name)
person1 = Person("Tom", 18)
person1.say_hello() #输出:Hello, my name is Tom
在上面的例子中,我们定义了一个Person
类,它有两个属性name
和age
,以及一个方法say_hello
。通过实例化这个类,我们可以创建一个person1
对象,并调用它的say_hello
方法。
在类的定义中,有一个特殊的方法__init__
,它是一个构造方法,用于初始化对象的属性。构造方法在对象创建时自动调用,并可以接收参数,用于设置对象的属性。
除了初始化方法__init__
,类还可以定义其他方法。在方法内部,可以使用self
关键字来引用对象的属性和方法。通过self
关键字,我们可以实现对象对自身属性和方法的访问和调用。
在Python中,对象可以直接访问类的属性和方法。属性可以通过对象名.属性名的方式进行访问,方法可以通过对象名.方法名的方式进行调用。
除了属性和方法,类还可以定义类变量和类方法。类变量是所有实例共享的变量,可以通过类名.变量名或对象名.变量名的方式进行访问。类方法是可以访问类变量的方法,可以通过@classmethod
装饰器来定义。
以下是一个包含类变量和类方法的例子:
class Circle:
pi = 3.14 #类变量,表示圆周率
def __init__(self, radius):
self.radius = radius
def calculate_area(self):
return Circle.pi * (self.radius ** 2)
@classmethod
def update_pi(cls, new_pi):
cls.pi = new_pi
circle1 = Circle(3)
print(circle1.calculate_area()) #输出:28.26
circle2 = Circle(5)
print(circle2.calculate_area()) #输出:78.5
Circle.update_pi(3.14159)
print(circle1.calculate_area()) #输出:28.27431
print(circle2.calculate_area()) #输出:78.53975
在上面的例子中,我们定义了一个Circle
类,它有一个类变量pi
表示圆周率。通过类变量pi
,我们可以在任何实例中访问和使用这个变量。同时,我们还定义了一个类方法update_pi
,用于更新类变量pi
的值。通过类方法update_pi
,我们可以修改类变量的值,并且会影响到所有实例。
封装
封装是面向对象编程的一个核心概念,它是将数据和方法包装在一个抽象的实体中,对外部隐藏了对象的内部细节。在Python中,可以使用访问修饰符来实现封装,包括public
、private
和protected
。这些访问修饰符可以在属性或方法前加上单下划线、双下划线和双下划线加单下划线来实现。
在Python中,封装可以通过类的属性和方法来实现。例如:
class Student:
def __init__(self, name, age):
self.name = name
self.age = age
def get_name(self):
return self.name
def get_age(self):
return self.age
在这个例子中,学生的姓名和年龄被封装在对象内部,外部只能通过get_name
和get_age
方法来获取。这样可以保证学生的信息不会被外部随意修改。
以下是另一个封装的例子:
class Person:
def __init__(self, name, gender):
self.name = name #public属性
self.__gender = gender #private属性
def say_hello(self):
print("Hi, my name is", self.name)
def __show_gender(self):
print("My gender is", self.__gender)
def show_info(self):
self.__show_gender() #内部调用private方法
person1 = Person("Tom", "Male")
person1.say_hello() #输出:Hi, my name is Tom
person1.__show_gender() #报错:AttributeError: 'Person' object has no attribute '__gender'
person1.show_info() #输出:My gender is Male
继承
继承是面向对象编程中的另一个核心概念,它使一个类可以从另一个类中继承属性和方法,而不需要重新定义。在Python中,可以使用关键字super
来实现父类的调用。
以下是一个继承的例子:
# 父类
class Animal:
def __init__(self, name):
self.name = name
def eat(self):
print(self.name, "is eating.")
# 子类继承父类
class Cat(Animal):
def __init__(self, name, color):
super().__init__(name) #调用父类的构造方法
self.color = color
def catch_mouse(self):
print(self.name, "is catching mouse.")
cat1 = Cat("Tom", "Black")
cat1.eat() #输出:Tom is eating.
cat1.catch_mouse() #输出:Tom is catching mouse.
多态
多态是面向对象编程中的第三个核心概念,它使不同的类可以使用相同的方法名实现不同的方法。在Python中,可以通过重写方法和类的多态性来实现。
以下是一个多态的例子:
# 父类
class Animal:
def __init__(self, name):
self.name = name
def sound(self):
print("The animal is making sound.")
# 子类一
class Dog(Animal):
def sound(self):
print("The dog is barking.")
# 子类二
class Cat(Animal):
def sound(self):
print("The cat is meowing.")
animal1 = Animal("Unknown")
animal1.sound() #输出:The animal is making sound.
dog1 = Dog("Teddy")
dog1.sound() #输出:The dog is barking.
cat1 = Cat("Tom")
cat1.sound() #输出:The cat is meowing.
为了深入介绍Python面向对象编程的应用,我选择实现一个简单的游戏来帮助初学者更好地理解和使用Python面向对象编程。
这个游戏的目标是让玩家控制一个小球躲避障碍物,每次成功躲避障碍物得1分,当玩家撞上障碍物时游戏结束,显示最终得分。
首先,我们需要创建一个Ball
类来表示小球,该类需要有位置、速度、大小等属性;还需要有更新位置、绘制等方法。代码示例如下:
import pygame
class Ball:
def __init__(self, screen, color, pos, radius, speed):
self.screen = screen
self.color = color
self.pos = pos
self.radius = radius
self.speed = speed
def draw(self):
pygame.draw.circle(self.screen, self.color, self.pos, self.radius)
def update(self):
self.pos[0] += self.speed[0]
self.pos[1] += self.speed[1]
然后,我们需要创建一个Obstacle
类来表示障碍物,该类需要有位置、大小等属性;还需要有更新位置、绘制等方法。代码示例如下:
class Obstacle:
def __init__(self, screen, color, pos, size, speed):
self.screen = screen
self.color = color
self.pos = pos
self.size = size
self.speed = speed
def draw(self):
pygame.draw.rect(self.screen, self.color, (self.pos[0], self.pos[1],
self.size[0], self.size[1]))
def update(self):
self.pos[0] += self.speed[0]
self.pos[1] += self.speed[1]
接着,我们需要创建一个Game
类来表示游戏,该类需要初始化游戏窗口、玩家得分、小球、障碍物等属性;还需要有更新游戏、处理碰撞等方法。代码示例如下:
class Game:
def __init__(self):
pygame.init()
self.screen_width = 640
self.screen_height = 480
self.screen = pygame.display.set_mode((self.screen_width,
self.screen_height))
self.bg_color = (255, 255, 255)
self.score = 0
self.ball = Ball(self.screen, (0, 0, 255), [100, 100], 20, [5, 5])
self.obstacle = Obstacle(self.screen, (255, 0, 0), [500, 300],
[50, 50], [-5, -5])
def run(self):
clock = pygame.time.Clock()
while True:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
self.screen.fill(self.bg_color)
self.ball.draw()
self.obstacle.draw()
self.ball.update()
self.obstacle.update()
if self.check_collision():
self.game_over()
return
pygame.display.flip()
def check_collision(self):
if ((self.ball.pos[0] + self.ball.radius > self.obstacle.pos[0] and
self.ball.pos[0] - self.ball.radius < self.obstacle.pos[0] +
self.obstacle.size[0]) and (self.ball.pos[1] + self.ball.radius >
self.obstacle.pos[1] and self.ball.pos[1] - self.ball.radius <
self.obstacle.pos[1] + self.obstacle.size[1])):
return True
return False
def game_over(self):
print("游戏结束!您的得分为:", self.score)
if __name__ == "__main__":
game = Game()
game.run()
在这个小游戏中,我们使用了Ball
、Obstacle
和Game
三个类来实现面向对象编程。通过定义不同的属性和方法,代码结构更清晰,易于维护和扩展。
Python在自然语言处理领域的应用也非常广泛。通过使用jieba
和NLTK
等模块,我们可以轻松地对中文字符串进行分词和词性标注。例如,我们可以使用jieba.cut
函数对中文字符串进行分词,然后使用NLTK
中的word_tokenize
和pos_tag
函数对分词结果进行词性标注。
Python和面向对象编程的学习对于初学者来说可能有些困难,但通过对基础知识的学习并结合实践,我们可以逐渐掌握Python的编程技巧和应用。使用Python进行面向对象编程可以使程序结构更清晰、易于扩展和维护。同时,Python在自然语言处理等领域的应用也为我们提供了丰富的工具和库。
代码案例和练习题
以下是一个简单的代码案例和一个练习题:
代码案例
假设有一个形状Shape
类,它有一个calculate_area
的方法用于计算面积,现在需要定义一个矩形Rectangle
类和圆形Circle
类,这两个类都继承自Shape
类,并且需要重写calculate_area
方法。
# 定义Shape类
class Shape:
def calculate_area(self):
pass
# 定义Rectangle类
class Rectangle(Shape):
def __init__(self, width, height):
self.width = width
self.height = height
def calculate_area(self):
return self.width * self.height
# 定义Circle类
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def calculate_area(self):
return 3.14 * self.radius ** 2
# 创建Rectangle实例
rectangle1 = Rectangle(10, 5)
print(rectangle1.calculate_area()) #输出:50
# 创建Circle实例
circle1 = Circle(3)
print(circle1.calculate_area()) #输出:28.26
练习题
定义一个类用于描述坐标系上的点,定义其属性为x
和y
,定义其方法为移动点move
和计算与另一点的距离calc_distance
。其中,移动点方法需要接收两个参数,分别表示x轴和y轴的移动量;计算距离方法需要接收一个点类的实例,并计算该点与当前点的距离,并且使用assert
语句进行测试。
import math #导入math库
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def move(self, dx, dy):
self.x += dx
self.y += dy
def calc_distance(self, point):
distance = math.sqrt((self.x - point.x) ** 2 + (self.y - point.y) ** 2)
return distance
# 测试
point1 = Point(0, 0)
point2 = Point(3, 4)
assert point1.calc_distance(point2) == 5.0 #计算(0,0)和(3,4)的距离为5
point1.move(1, 2)
assert point1.calc_distance(point2) == math.sqrt(10) #计算(1,2)和(3,4)的距离为根号10