8个Python面向对象编程的技巧

8个Python面向对象编程的技巧

面向对象编程语言是一种广泛应用于软件设计的编程范式,它使代码可重用并减少代码冗余。它使用类和对象来实现编程中的现实世界对象。Python和其他语言如C++Java、JavaScript等都支持面向对象编程。在本文中,我们将了解面向对象编程的特点以及在Python中使用面向对象编程的一些技巧。

在面向对象编程中,对象是从其类蓝图创建的。这些对象代表现实世界对象,因为它们具有某些称为属性和方法的属性,就像现实世界对象具有自己的属性和行为一样。例如,如果我们将狗视为现实世界对象,则它具有品种、颜色、大小等属性,还具有吠叫、奔跑速度等行为。这些属性和行为可以封装在一个狗对象中,该对象将具有其自己的属性和方法来表示编程中的一只狗。

面向对象编程具有4个特征,可以使代码更模块化、可重用和可维护 –

继承

在继承中,从已有类创建一个新类,即新类使用现有类的方法和行为,使代码更可重用和可维护。继承还使新类具有向新类中添加新函数的功能,以及在继承类中覆盖旧类的现有函数。继承减少了代码复杂性,使代码更可重用和可扩展。

封装

封装是将数据和使用该数据的函数封装在一个实体中的过程。面向对象编程将数据及其使用该数据的函数封装在类中,并以受控的方式允许访问和修改该数据和函数。封装使用访问修饰符如public、private和protected来提供对类的数据和函数的受限访问。

多态

通过多态来实现对象在不同情况下以不同方式行为。在面向对象编程中,可以通过方法重载和方法重写来实现多态。方法重载是创建具有相同名称但不同参数的多个方法的过程,而方法重写是在子类中创建方法的新实现的过程。多态使开发人员能够编写更加灵活和适应性强的代码,更容易向系统中添加新功能或特性,而不会破坏现有代码。

数据抽象

抽象是隐藏对象的实现细节并仅显示功能的过程。由于抽象,用户能够知道函数在做什么,但无法理解其工作原理或函数的内部细节。抽象使开发人员能够创建系统的高级视图,使代码的复杂性更易于理解和管理。

现在,让我们来看看在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类,并定义了属性,如“name”,“age”和“occupation”。

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.

区分类级别和实例级别数据

由于继承是面向对象编程的重要支柱,因此有必要区分类级别和实例级别的数据以更好地理解继承。一个类的实例的属性限定于该对象,这些属性在类的构造函数中定义,而专属于类的属性则在类的构造函数之外定义。

示例

在下面的示例中,我们创建了一个名为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

Pep8指南

在2001年,Guido van Rossum、Barry Warsaw和Nick Coghlan创建了一些编码规范,这些规范在创建Python包时必须注意。 这些编码规范被称为Python企业提案或PEP指南。 除了代码质量之外,在创建Python包时还应注意其他因素。 所有这些因素都在PEP指南中提到。 一些重要因素包括:

  • 每行代码的长度不得超过80个字符

  • 在代码开头导入所有所需的库。

  • 不要在代码中使用冗余变量。

示例

在下面的示例中,我们以两种不同的方式创建了一个 calculate_area 方法。 良好的示例是使用pep8指南实现的,而坏的示例则没有遵循pep8指南。

# 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

结论

在这篇文章中,我们讨论了用适当的例子介绍了面向对象编程的各种技巧。通过遵循本文中讨论的技巧,我们可以编写出良好组织、模块化且易于维护的面向对象的代码。

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程