跳转至

第 21 天:类和对象

📘 第21天

类和对象

Python是一种面向对象的编程语言。在Python中,一切都是对象,都有其属性和方法。在程序中使用的数字、字符串、列表、字典、元组、集合等都是相应内置类的对象。我们创建类来创建对象。类就像一个对象构造器,或者说是创建对象的"蓝图"。我们实例化一个类来创建一个对象。类定义了对象的属性和行为,而对象则代表了类。

从这个挑战的开始,我们就一直在不知不觉地使用类和对象。Python程序中的每个元素都是某个类的对象。 让我们检查一下Python中的一切是否都是类:

Python
asabeneh@Asabeneh:~$ python
Python 3.9.6 (default, Jun 28 2021, 15:26:21)
[Clang 11.0.0 (clang-1100.0.33.8)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> num = 10
>>> type(num)
<class 'int'>
>>> string = 'string'
>>> type(string)
<class 'str'>
>>> boolean = True
>>> type(boolean)
<class 'bool'>
>>> lst = []
>>> type(lst)
<class 'list'>
>>> tpl = ()
>>> type(tpl)
<class 'tuple'>
>>> set1 = set()
>>> type(set1)
<class 'set'>
>>> dct = {}
>>> type(dct)
<class 'dict'>

创建类

要创建一个类,我们需要关键字class,后跟类名和冒号。类名应该使用驼峰命名法(CamelCase)

Bash
# 语法
class 类名:
  代码放在这里

示例:

Python
class Person:
  pass
print(Person)
Bash
<__main__.Person object at 0x10804e510>

创建对象

我们可以通过调用类来创建对象。

Python
p = Person()
print(p)

类构造函数

在上面的例子中,我们已经从Person类创建了一个对象。然而,没有构造函数的类在实际应用中并不真正有用。让我们使用构造函数使我们的类更有用。与Java或JavaScript中的构造函数一样,Python也有一个内置的init()构造函数。init构造函数有一个self参数,它是当前类实例的引用。 示例:

Python
class Person:
      def __init__ (self, name):
        # self允许将参数附加到类
          self.name = name

p = Person('Asabeneh')
print(p.name)
print(p)
Bash
# 输出
Asabeneh
<__main__.Person object at 0x2abf46907e80>

让我们向构造函数添加更多参数。

Python
class Person:
      def __init__(self, firstname, lastname, age, country, city):
          self.firstname = firstname
          self.lastname = lastname
          self.age = age
          self.country = country
          self.city = city


p = Person('Asabeneh', 'Yetayeh', 250, 'Finland', 'Helsinki')
print(p.firstname)
print(p.lastname)
print(p.age)
print(p.country)
print(p.city)
Bash
# 输出
Asabeneh
Yetayeh
250
Finland
Helsinki

对象方法

对象可以有方法。方法是属于对象的函数。

示例:

Python
class Person:
      def __init__(self, firstname, lastname, age, country, city):
          self.firstname = firstname
          self.lastname = lastname
          self.age = age
          self.country = country
          self.city = city
      def person_info(self):
        return f'{self.firstname} {self.lastname}今年{self.age}岁。他住在{self.country}{self.city}。'

p = Person('Asabeneh', 'Yetayeh', 250, 'Finland', 'Helsinki')
print(p.person_info())
Bash
# 输出
Asabeneh Yetayeh今年250岁。他住在Finland的Helsinki。

对象默认方法

有时,你可能希望为对象方法提供默认值。如果我们为构造函数中的参数提供默认值,可以避免在不带参数调用或实例化类时出现错误。让我们看看这是什么样子:

示例:

Python
class Person:
      def __init__(self, firstname='Asabeneh', lastname='Yetayeh', age=250, country='Finland', city='Helsinki'):
          self.firstname = firstname
          self.lastname = lastname
          self.age = age
          self.country = country
          self.city = city

      def person_info(self):
        return f'{self.firstname} {self.lastname}今年{self.age}岁。他住在{self.country}{self.city}。'

p1 = Person()
print(p1.person_info())
p2 = Person('John', 'Doe', 30, 'Nomanland', 'Noman city')
print(p2.person_info())
Bash
# 输出
Asabeneh Yetayeh今年250岁。他住在Finland的Helsinki。
John Doe今年30岁。他住在Nomanland的Noman city。

修改类默认值的方法

在下面的例子中,person类的所有构造函数参数都有默认值。此外,我们还有一个skills参数,可以通过方法访问。让我们创建一个add_skill方法,向skills列表添加技能。

Python
class Person:
      def __init__(self, firstname='Asabeneh', lastname='Yetayeh', age=250, country='Finland', city='Helsinki'):
          self.firstname = firstname
          self.lastname = lastname
          self.age = age
          self.country = country
          self.city = city
          self.skills = []

      def person_info(self):
        return f'{self.firstname} {self.lastname}今年{self.age}岁。他住在{self.country}{self.city}。'
      def add_skill(self, skill):
          self.skills.append(skill)

p1 = Person()
print(p1.person_info())
p1.add_skill('HTML')
p1.add_skill('CSS')
p1.add_skill('JavaScript')
p2 = Person('John', 'Doe', 30, 'Nomanland', 'Noman city')
print(p2.person_info())
print(p1.skills)
print(p2.skills)
Bash
# 输出
Asabeneh Yetayeh今年250岁。他住在Finland的Helsinki。
John Doe今年30岁。他住在Nomanland的Noman city。
['HTML', 'CSS', 'JavaScript']
[]

继承

继承允许我们定义一个继承父类所有功能的类。它使代码可重用。

Python
# 语法
class 子类名(父类名):
    代码放在这里

让我们通过实际例子来看看继承的含义:

Python
class Student(Person):
    pass


s1 = Student('Eyob', 'Yetayeh', 30, 'Finland', 'Helsinki')
s2 = Student('Lidiya', 'Teklemariam', 28, 'Finland', 'Espoo')
print(s1.person_info())
s1.add_skill('JavaScript')
s1.add_skill('React')
s1.add_skill('Python')
print(s1.skills)
print(s2.person_info())
s2.add_skill('Organizing')
s2.add_skill('Marketing')
s2.add_skill('Digital Marketing')
print(s2.skills)
Bash
# 输出
Eyob Yetayeh今年30岁。他住在Finland的Helsinki。
['JavaScript', 'React', 'Python']
Lidiya Teklemariam今年28岁。他住在Finland的Espoo。
['Organizing', 'Marketing', 'Digital Marketing']

我们没有在Student类中调用任何方法,但我们能够访问来自Parent类的所有方法。Student类继承了Person类的__init__构造函数和person_info方法。如果我们想要向子类添加一个特定于子类的新方法,我们必须编写子类并在子类中创建新的方法。

Python
class Student(Person):
    def __init__ (self, firstname='Asabeneh', lastname='Yetayeh',age=250, country='Finland', city='Helsinki', gender='male'):
        self.gender = gender
        super().__init__(firstname, lastname,age, country, city)
    def person_info(self):
        gender = '他' if self.gender =='male' else '她'
        return f'{self.firstname} {self.lastname}今年{self.age}岁。{gender}住在{self.country}{self.city}。'


s1 = Student('Eyob', 'Yetayeh', 30, 'Finland', 'Helsinki','male')
s2 = Student('Lidiya', 'Teklemariam', 28, 'Finland', 'Espoo', 'female')
print(s1.person_info())
s1.add_skill('JavaScript')
s1.add_skill('React')
s1.add_skill('Python')
print(s1.skills)
print(s2.person_info())
s2.add_skill('Organizing')
s2.add_skill('Marketing')
s2.add_skill('Digital Marketing')
print(s2.skills)
Bash
# 输出
Eyob Yetayeh今年30岁。他住在Finland的Helsinki。
['JavaScript', 'React', 'Python']
Lidiya Teklemariam今年28岁。她住在Finland的Espoo。
['Organizing', 'Marketing', 'Digital Marketing']

我们可以使用super()函数或父类名Person来自动继承父类的方法和属性。在上面的例子中,我们覆盖了父类方法。子类的person_info方法有不同的实现,即使方法名称与父类相同。

覆盖父类方法

如上所示,我们可以通过创建与父类方法名称相同的子类方法来覆盖父类方法。

💻 练习:第21天

练习:级别1

  1. Python有一个名为_statistics_的模块,我们可以使用这个模块来计算统计数据。但是,让我们尝试开发一个可以计算均值、中位数、众数、标准差等统计数据的类。
Python
class Statistics:
    def __init__(self, data=[]):
        self.data = data

    def count(self):
        # 你自己的实现
        pass

    def sum(self):
        # 你自己的实现
        pass

    def min(self):
        # 你自己的实现
        pass

    def max(self):
        # 你自己的实现
        pass

    def range(self):
        # 你自己的实现
        pass

    def mean(self):
        # 你自己的实现
        pass

    def median(self):
        # 你自己的实现
        pass

    def mode(self):
        # 你自己的实现
        pass

    def standard_deviation(self):
        # 你自己的实现
        pass

    def variance(self):
        # 你自己的实现
        pass

    def frequency_distribution(self):
        # 你自己的实现
        pass

    def describe(self):
        # 你自己的实现
        pass
Python
# 测试代码
data = [31, 26, 34, 37, 27, 26, 32, 32, 26, 27, 27, 24, 32, 33, 27, 25, 26, 38, 37, 31, 34, 24, 33, 29, 26]
statistics = Statistics(data)
print('Count:', statistics.count()) # 25
print('Sum: ', statistics.sum()) # 730
print('Min: ', statistics.min()) # 24
print('Max: ', statistics.max()) # 38
print('Range: ', statistics.range()) # 14
print('Mean: ', statistics.mean()) # 29.2
print('Median: ', statistics.median()) # 27
print('Mode: ', statistics.mode()) # {'mode': 26, 'count': 5}
print('Standard Deviation: ', statistics.standard_deviation()) # 4.2
print('Variance: ', statistics.variance()) # 17.5
print('Frequency Distribution: ', statistics.frequency_distribution()) # [(24, 2), (25, 1), (26, 5), (27, 4), (29, 1), (31, 2), (32, 3), (33, 2), (34, 2), (37, 2), (38, 1)]

练习:级别2

  1. 创建一个名为PersonAccount的类。它有firstname、lastname、incomes、expenses属性和添加收入、添加支出以及账户余额方法。

练习:级别3

  1. 以下是使用函数的方法。让我们将其转换为类
Python
def print_products(*args, **kwargs):
    for product in args:
        print(product)
    print(kwargs)
    for key in kwargs:
        print(f"{key}: {kwargs[key]}")

print_products("apple", "banana", "orange", vegetable="tomato", juice="orange")
Bash
apple
banana
orange
{'vegetable': 'tomato', 'juice': 'orange'}
vegetable: tomato
juice: orange
  1. 在一个名为PersonAccount的类中,我们有属性:firstname、lastname、incomes、expenses。设计一个类,用于计算一个人的净收入。

🎉 恭喜!🎉

<< 第20天 | 第22天 >>

评论