Python面向对象编程的8个技巧
面向对象编程语言是一种广泛应用于软件设计的编程范式,因为它可以提高代码的可重用性并减少代码冗余。它使用类和对象在编程中实现现实世界中的对象。Python和其他语言(如C++、Java、Javascript等)都支持面向对象编程。在本文中,我们将了解面向对象编程的特点以及在Python中使用面向对象编程的一些技巧。
在面向对象编程中,对象是由其类蓝图创建的。这些对象代表现实世界中的对象,因为它们具有一些称为属性的方法,就像现实世界中的对象具有自身的属性和行为一样。例如,如果我们将狗视为现实世界中的对象,那么它具有一定的属性,例如品种、颜色、大小,以及一些行为,例如吠叫、奔跑速度等。这些属性和行为可以封装在一个Dog对象中,该对象将具有其属性和方法来在编程中表示一只狗。
面向对象编程具有4个特性,可以使代码更模块化、更可重用和更易于维护:
继承
在继承中,一个新类是从一个已存在的类创建的,即新类使用现有类的方法和行为,这使得代码更易于重用和维护。继承还提供了向新类添加新函数以及在继承类中覆盖旧类现有函数的功能。继承降低了代码复杂性,使代码更易于重用和扩展。
封装
封装是将数据及其使用该数据的函数封装到单个实体中的过程。OOP将数据及其使用该数据的函数封装在类中,并允许以受控的方式访问和修改该数据和函数。封装使用public、private和protected等访问修饰符来限制对类的数据和函数的访问。
多态
对象在不同情况下以不同方式运行是通过多态实现的。在OOP中,多态可以通过方法重载和方法覆盖来实现。方法重载是在创建多个具有相同名称但参数不同的方法的过程,而方法覆盖是在子类中创建方法的新实现的过程。多态允许开发人员编写更灵活和更易于适应的代码,从而更容易向系统添加新功能或特性,而不会破坏现有代码。
数据抽象
抽象是隐藏对象实现细节并仅显示功能的过程。由于抽象,用户能够知道函数的作用,但无法理解其工作方式或函数的内部细节。抽象允许开发人员创建系统的更高级别的视图,从而更容易理解和管理代码的复杂性。
现在,让我们来看一些在Python中进行面向对象编程的技巧:
使用类来建模任何现实世界中的对象
类是定义对象属性和方法的蓝图。在创建对象之前,确保它是从有效的类创建的,因为当我们创建类的实例时,我们创建了一个对象,其属性具有实际值。
示例
如果您正在创建一个游戏,首先为玩家、敌人、武器和物品创建类,然后创建这些类的实例来创建游戏逻辑。
class Player:
def __init__(self, player_name):
self.player_name = player_name
class Enemy:
def __init__(self, enemy_name, enemy_health):
self.enemy_name = enemy_name
self.enemy_health = enemy_health
class Weapon:
def __init__(self, weapon_name, weapon_damage):
self.weapon_name = weapon_name
self.weapon_damage = weapon_damage
class Game:
def __init__(self, players, enemies, weapons):
self.players = players
self.enemies = enemies
self.weapons = weapons
def start_game(self):
print("Game has started")
def end_game(self):
print("Game has ended")
# create some players, enemies, and weapons
player1 = Player("John")
player2 = Player("Jane")
enemy1 = Enemy("Zombie", 50)
enemy2 = Enemy("Goblin", 75)
weapon1 = Weapon("Sword", 25)
weapon2 = Weapon("Axe", 30)
# create a game object with the players, enemies, and weapons
game = Game([player1, player2], [enemy1, enemy2], [weapon1, weapon2])
# start the game
game.start_game()
# play the game...
# end the game
game.end_game()
输出
Game has started Game has ended
使用有意义的命名约定
为类以及类中定义的属性和函数使用有意义的名称。名称应指定类的行为和函数。在业界,驼峰式命名法用作默认命名约定。始终确保一个类、属性和方法只负责一项任务。
示例
在下面的示例中,创建了一个Person类,类名为“Person”,属性如姓名、年龄和职业。
class Person:
def __init__(self, person_name, person_age,person_occupation):
# type: (str, int, str) -> None
self.person_name = person_name
self.person_age = person_age
self.person_occupation = person_occupation
def introduce(self):
# type: () -> str
return "Myself {}, I am {} years old, and I work as a {}.".format(self.person_name, self.person_age, self.person_occupation)
# Create a person object
person1 = Person("John Smith", 35, "Software Engineer")
# Call the introduce method to get the person's introduction
introduction = person1.introduce()
# Print the introduction
print(introduction)
输出
Myself John Smith, I am 35 years old, and I work as a Software Engineer.
区分类级别数据和实例级别数据
由于继承是OOPs的重要支柱,因此有必要区分类级别数据和实例级别数据,以便更好地理解继承。类的实例属性仅限于该对象,这些属性是在类的构造函数内定义的;而专门属于类的属性是在类的构造函数外部定义的。
示例
在下面的示例中,我们创建了一个具有类级别属性和实例级别属性的Car类。类级别属性和实例级别属性可以按如下方式访问:
class Car:
# class-level attribute
category = 'Vehicle'
def __init__(self, make, model):
# instance-level attribute
self.make = make
self.model = model
# creating instances of Car class
car1 = Car('Toyota', 'Corolla')
car2 = Car('Honda', 'Civic')
# accessing class-level attribute
print(Car.category) # output: Vehicle
# accessing instance-level attributes
print(car1.make, car1.model) # output: Toyota Corolla
print(car2.make, car2.model) # output: Honda Civic
# changing class-level attribute value
Car.category = 'Automobile'
# accessing updated class-level attribute
print(Car.category) # output: Automobile
# changing instance-level attribute value
car1.make = 'Nissan'
# accessing updated instance-level attribute
print(car1.make, car1.model) # output: Nissan Corolla
输出
Vehicle Toyota Corolla Honda Civic Automobile Nissan Corolla
使用多态编写灵活的代码
多态是函数或对象可以用不同形式使用的方法。使用多态,您可以编写灵活的代码,使来自不同类的对象可以互换地使用相同的函数,从而减少代码并避免冗余。例如,如果您有一个以对象列表作为参数的函数,则可以传入具有相同接口的任何对象的列表。这允许您编写可以与各种对象一起工作的通用代码。
Python中的文档字符串
为了更好地理解代码,开发人员会在代码中编写注释,以便其他人阅读时能够轻松理解函数的作用。但这对于大型Python包、模块和函数来说不是一种方便的方式。因此,Python结构化文档(也称为文档字符串)提供了一种方便的方式来记录公共Python包、函数和方法,以描述函数的作用。您可以使用“'''三单引号'''”或“"""三双引号"""”在Python中编写文档字符串。
示例
在下面的示例中,我们创建了一个名为calculate_area的函数,用于计算给定长和宽的矩形的面积。文档字符串用三引号括起来,描述了函数、函数的参数和函数的返回类型。
def calc_area(len, wid):
"""
Given the length and width of the rectangle , calculate its area.
Parameters:
len (float): The length of the rectangle.
wid (float): The width of the rectangle.
Returns:
Float: Reactangle calculated area.
"""
area = length * width
return area
我们可以使用help函数访问文档字符串,如下所示:
print(help(calculate_area)) print(calculate_area.__doc__)
输出
Help on function calc_area in module __main__:
calc_area(len, wid)
Given the length and width of the rectangle , calculate its area.
Parameters:
len (float): The length of the rectangle.
wid (float): The width of the rectangle.
Returns:
Float: Reactangle calculated area.
None
Given the length and width of the rectangle , calculate its area.
Parameters:
len (float): The length of the rectangle.
wid (float): The width of the rectangle.
Returns:
Float: Reactangle calculated area.
设置属性访问
属性是在类内定义的对象属性,对象使用它们来获取、设置或更新其值及其关联的方法。Python提供一些内置函数来访问和操作类的属性。
getattr() - 此函数用于获取或访问属性的值。
setattr() - 此函数用于更新属性的值。
hasattr() - 此函数用于检查属性是否存在。
delattr() - 此函数用于删除属性。
示例
在下面的示例中,我们使用getter和setter函数设置Car类属性的访问权限,如下所示:
class Car:
def __init__(self, car_company, car_model):
self.car_company = car_company
self.car_model = car_model
car1 = Car('Toyota', 'Corolla')
# setting attribute value using setattr
setattr(car1, 'color', 'red')
# getting attribute value using getattr
print(getattr(car1, 'car_company')) # output: Toyota
# checking attribute existence using hasattr
print(hasattr(car1, 'car_model')) # output: True
print(hasattr(car1, 'year')) # output: False
# deleting attribute using delattr
delattr(car1, 'color')
print(hasattr(car1, 'color')) # output: False
输出
Toyota True False False
使用抽象类
抽象类为组件的实现提供了通用接口。在抽象类中创建的方法可以在从抽象类创建的任何子类中使用。抽象类减少了开发人员的代码量,并使代码更易于维护。
示例
在下面的示例中,我们创建了一个名为Animal的抽象类,其中包含make_sound方法,并且所有其他从其继承的类都应实现make_sound方法。
try:
from abc import ABC, abstractmethod
except ImportError:
# Python 2.x fallback
class ABCMeta(type):
def __new__(cls, name, bases, namespace):
return type.__new__(cls, name, bases, dict(namespace))
class ABC(object):
__metaclass__ = ABCMeta
def abstractmethod(method):
method.__isabstractmethod__ = True
return method
class Animal(ABC):
@abstractmethod
def make_sound(self):
pass
class Cat(Animal):
def make_sound(self):
print("Meow")
class Dog(Animal):
def make_sound(self):
print("Woof")
# creating objects
cat = Cat()
dog = Dog()
# calling methods
cat.make_sound() # output: Meow
dog.make_sound() # output: Woof
输出
Meow Woof
PEP 8 指南
2001年,Guido van Rossum、Barry Warsaw和Nick Coghlan创建了一些编码约定,在创建Python包时必须注意这些约定。这些编码约定被称为Python增强提案或PEP指南。除了代码质量之外,在创建Python包时还应注意其他因素。PEP指南中提到了所有这些因素。一些重要的因素是:
每一行代码应限制在80个字符以内。
在代码开头导入所有所需的库。
不要在代码中使用冗余变量。
示例
在下面的示例中,我们以两种不同的方式创建了一个calculate_area方法。好的示例是使用PEP 8指南实现的,而不好的示例没有遵循PEP 8指南。
# Good Example def calc_area(wid, ht): """Calculate the area of a rectangle.""" calculated_area = wid * ht return calculated_area # Bad Example def Calc_Area(Wid, Ht): calculated_area=Wid*Ht return calculated_area # PEP 8 naming conventions print(calc_area.__name__) print(Calc_Area.__name__)
输出
calc_area Calc_Area
结论
在本文中,我们讨论了面向对象编程的各种技巧以及相应的示例。通过遵循本文中讨论的技巧,我们可以编写组织良好、模块化且易于维护的面向对象代码。
数据结构
网络
关系数据库管理系统(RDBMS)
操作系统
Java
iOS
HTML
CSS
Android
Python
C语言编程
C++
C#
MongoDB
MySQL
Javascript
PHP