(翻译)30天学习Python👨‍💻第八天——面向对象基础

277 阅读5分钟

30天学习Python👨‍💻第八天——面向对象基础

介绍

Python是一种多范式的编程语言,这非常有趣。我意识到JavaScript也是一种多范式的编程语言。

这意味在我们可以有多种思考如何编写构造Python代码的方式。但是这为什么很重要呢?在现实中,当我们开发真实项目时,我们尝试用程序解决复杂的问题,甚至在还没有写一行代码之前就要进行很多次的头脑风暴。好的程序不只是考虑我们如何解决问题,还要考虑代码的可维护性、可扩展性,以及可读性。这种构造和组织代码的方式被称为编程范式。这是一种预先规定好规则,开发者需要遵守以避免混乱的模式。如果每个开发者都用他们自己的方式编写代码,那会让人震惊。

让我们回到Python。

在Python中,一切皆对象。我探讨过的所有数据类型都是对象,它们都有自己的属性和方法。这些对象称为实例,产生于它们的类。这意味着Python中所有的数据类型都有一个已定义的结构或者原型,它们所有的属性和方法都在这里被定义。

print(type(2)) # <class 'int'>
print(type(2.5)) # <class 'float'>
print(type('Python')) # <class 'str'>
print(type(True)) # <class 'bool'>
print(type({})) # <class 'dict'>
print(type([])) # <class 'list'>
print(type(())) # <class 'tuple'>
print(type(None)) # <class 'NoneType'>

和内置的类一样,自定义的类可以代表真实世界中的事物,比如汽车、机器、人类、动物等任何东西。真实世界中的物体以及它们的属性和行为在代码中用类表示,可以作为面向对象编程范式的松散定义。所有的类都可以被用作产生一个实例对象。这些对象可以与其他对象结合以模拟现实世界的功能。

在JavaScript中,自定义类也可以被创建(尽管ES6中的class只是函数原型的高级语法糖)。所以在我的思维模型中,我把它们联系起来。

面向对象基础

但是想要看到Python中面向对象的强大,我们需要深入研究并且编写一些代码。

class Avenger:
  def __init__(self, name):
    self.name = name

  def fight(self):
    print('👊')

spiderman = Avenger('Spiderman')

print(type(Avenger)) # <class 'type'>
print(type(spiderman)) # <class '__main__.Avenger'> --> Avenger的实例

在Python中,类的命名可以是驼峰式,而不用像变量那样需要采用蛇形的命令方式。

上面代码中的__init__是一个初始化方法(也称为构造方法)。它用来初始化类的变量。在上面的类定义中,name进行了初始化。这和JavaScript中,类的构造函数非常的相像。

self是Python中的一个关键字,它表示类的实例的引用,用于访问类的变量或属性。在我的认知中,我觉得这和JavaScript中的this很像。

在上面的Avenger 类中,fight 是一个方法,假设当fight 被要求“战斗”(调用)时,它会怎么做?这里它只打印一个表情符号,但其实可以是任何动作。

Avenger 作为原型,我创建了Spiderman 对象。类似的,这个类可以用于创造任何其他avengers 的对象,但似乎每个人都会做同样的事情,执行fight方法,这一点都没意思。

class Avenger:
  def __init__(self, name, weapon):
    self.name = name
    self.weapon = weapon

  def fight(self):
    print(self.weapon)

spiderman = Avenger('Spiderman', 'dispatch a web')
thor = Avenger('Thor', 'thunder attack')

spiderman.fight() # dispatch a web
thor.fight() # thunder attack

这样好一些了。每一个avenger 都有不同的表现。这是一个类的最简结构,可以给它添加许多功能让它更加复杂。

当对象被初始化(创建)的时,__init__构造方法每次都会被调用。它还提供了许多进行控制的机制,只允许在满足条件或向参数添加默认值时创建对象。

class MotorBike:
  def __init__(self, brand, age):
    if(age <= 15):
      self.brand = brand
      self.age = age

  def start(self):
    print(f'starting {self.brand}....')

bullet = MotorBike('Royal Enfield Bullet',20)
bullet.start() # 报错. 只要age小于15时对象才会被创建

代码练习

这个任务是创建一个带有namegoals属性的*SoccerPlayer* 类,然后创建三个对象,使用一个函数找出这些对象中goals最大的那个并把它打印出来。

class SoccerPlayer:
  def __init__(self, name, goals):
    self.name = name
    self.goals = goals


def calculateMaxGoals(*args):
  print(args)
  return max(*args)

messi = SoccerPlayer('messi', 10)
ronaldo = SoccerPlayer('ronaldo',22)
neymar = SoccerPlayer('neymar', 8)

max_goals = calculateMaxGoals(messi.goals, ronaldo.goals, neymar.goals)
print(f'The highest number of goals is {max_goals} goals')

装饰器@classmethod和@staticmethod

方法也可以附加到类,而不需要创建类的实例。

可以通过在方法名的头部添加@classmethod装饰器的方式,给类添加方法。我后面会探讨装饰器的细节,现在只要粗浅的理解为是创建了一个类的方法就可以了。

class Calculator:
  def __init__(self,type):
    self.type = type

  @classmethod
  def calculate_sum(cls, num1, num2): 
        return num1 + num2
    # cls就像self一样,它需要放在第一个参数的位置

print(Calculator.calculate_sum(3,5)) # 8

@staticmethod非常像classmethod。只是它不需要传入cls参数。这个方法可以在不需要类实例化的情况下被调用。

class Calculator:
  def __init__(self,type):
    self.type = type

  @staticmethod
  def multiply(num1, num2): 
        return num1 * num2

print(Calculator.multiply(3,5)) # 15

这就是今天全部的内容了。后面我将会探讨面向对象编程的细节,并且通过一些联系来理解这些概念。我们的知识体系正在稳定的扩展,以便于我们可以应对更加高级的内容。

我正在看这个Python创始人问答视频,非常有趣,现在分享给你:)

www.youtube.com/watch?v=7kn…

原文链接

30 Days of Python 👨‍💻 - Day 8 - OOP Basics