python中的类、方法以及实例

🎉🎉现在可以在这里下载notebook文档啦,便看便运行!

1. 前言

Python语言的特点不必再多说,在学习过程中,很重要的一部分内容就是Python的函数和类的编写及调用。

函数其实就是一个计算过程,对于合法的输入经过计算返回输出,对于非法的输入抛出相应的错误。

是对具有相似特性的实例的抽象,以集中管理此类对象的表现和特性。

2. 类的直观理解

2.1 从一个问题入手

假设我们需要用Python定义“张三”这个人,需要包括他的姓名、性别和年龄。

有许多Python的内置数据类型可以实现,比如说用字典:

one_person = {
	"name": "张三",
	"gender": "男",
	"age": "18"
}

这样,one_person这个变量就包含了张三的基本信息,只需要按照字典的访问方式,就可以获取相关属性的值:

print(f"Age of {one_person['name']} is: {one_person['age']}")
# Output:Age of 张三 is: 18

Note:
如果读者不熟悉f-strings,那么可以在这里了解更多。

类似地,如果我们想继续定义“李四”这个人,可以有如下写法:

another_person = {
	"name": "李四",
	"gender": "女",
	"age": "19"
}

用这种方法当然可以还可以定义其他的人,但每次都要把字典里面的属性名称,即namegenderage,都写一遍,可能会让人觉得烦躁。我们发现需要定义的人的属性种类是相同的,那么可不可以把它们抽象出来,用一种其他的方法来更加方便地定义一个个具体的人呢?

这种“其他的方法”,就是类。

2.2 定义及使用一个类

接上面的例子,我们需要定义“人”这个类,且要求它有三个属性:namegenderage。写法如下:

class Man:
	def __init__(self, name, gender, age):
		self.name = name
		self.gender = gender
		self.age = age

上述代码片的主要内容如下:

  • class关键字声明(定义)了一个类;
  • Man是类的名字;
  • Man类中,通过def关键字定义类一个“函数”:__init__,该函数有四个参数:selfnamegenderage

暂且不做更多的说明,先看如何使用这个类:

third_person = Man('王五', '男', '28')
forth_person = Man("周六", "男", "33")

然后打印一下相关的信息:

print(f"Age of {third_person.name} is: {third_person.age}")
# Output:Age of 王五 is: 28

2.3 解释

在用Man类来构造变量third_personforth_person时,我们发现这和函数的调用方法很相似,都是传入一些参数,获取一个返回值(当然,有些函数没有返回值)。实际上这个步骤叫做类的实例化,顾名思义,就是利用定义的Man类来实例化许多不同的“人”。

在这个例子中,third_personforth_person都是Man类的实例。关于这个结论,可以用以下的方法验证:

print(type(third_person))
# Output:<class '__main__.Man'>

或者

print(isinstance(third_person, Man))
# Output:True

实际上,Python的基础数据类型都是一个个的类,而具体的数据(对象)就是对应类的实例,例如,可以用isinstance(1, int)来验证1int的实例,用isinstance(1.0, float)来验证1.0float的实例,用isinstance(one_person, dict)来验证one_persondict的实例等。

既然third_personMan的一个实例,也就是一个具体的“人”,那么我们就应该有办法获取到这个人的姓名、性别和年龄属性。要实现这一点,可以利用obj.method的方式实现:

# 获取姓名
print(third_person.name)
# Output:王五

# 获取年龄
print(third_person.age)
# Output:28

更准确的来说,nameage是实例的属性,而类的实例有哪些属性,就是在定义类的时候写明的。

至此,就到了那个看上去很奇怪的“函数”:__init__登场了。

在本例中,Man类的实例一共有三个属性,这刚好是__init__“函数”的后三个参数。实际上,“init”就是“initialize”的缩写,其作用就是定义了类在实例化时所执行的操作。

Python规定了__init__“函数”的第一个参数必须为self,指代本身。通过self.name = name,就将实例化时传入的name绑定到了self上,而通过obj.method访问类的属性时,实际上访问的就是self的属性。

Note:

  • 实际上Python只是规定了__init__的第一个参数必须指代实例本身,而用self是约定的习惯而已,将Man中所有的self替换成其他的字符也是可以的;不过为了方便阅读和沟通,建议使用self
  • 定义在类中的函数,在Python中被称为方法,这也是上文出现的“函数”一词加引号的原因。
  • 以双下划线开头和结尾的方法,例如__init__,比较特殊,被称为魔术方法,它们往往要实现特定的作用,用户也可以通过重载这些方法来改变它们的表现。

3. 类的方法

接上面的例子,一个人不只是拥有静态的属性,还应该去参加必要的社会活动,例如:工作、运动、吃饭等等。与姓名、年龄等相比,这些活动具有一个显著的特点:它们是一个过程。

要实现这种过程,就需要在类中定义“方法”。

3.1 定义方法

前面已经提到,“方法”其实就是定义在类内的函数,而函数的作用就是执行一个过程,完成一项任务。

下面的代码定义了Man类的三种方法:

class Man:
    def __init__(self, name, gender, age):
        self.name = name
        self.gender = gender
        self.age = age

    def work(self):
        print(f"{self.name} is working.")

    def do_sports(self):
        print(f"{self.name} is doing sports.")

    def take_meal(self):
        print(f"{self.name} is taking a meal.")

work为例,它是我们为类定义的一个方法,该方法只有一个参数self,这意味着在该方法内部可以访问所有绑定到self上的属性,例如,self.nameself.genderself.age

one_person = Man('王五', '男', '28')
one_person.work()
# Output:王五 is working.
one_person.do_sports()
# Output:王五 is doing sports.
one_person.take_meal()
# Output:王五 is taking a meal.

调用某个方法,与调用属性的方式类似。由于方法是函数,因此,需要在后面加上(),即通过obj.methods()进行调用。

Note:

  • 再次注意,self指代的是实例本身,通过实例调用方法时,不用给该参数传值,python会自动处理;
  • 事实上,如果通过类来调用方法,那么就需要传入第一个参数了:
# 一般不这样写,但确实没有语法错误
one_person = Man('王五', '男', '28')
Man.take_meal(one_person)

3.2 方法内调用其他方法

既然self指代类本身,那么通过self应该也可以在方法内部调用其他方法。

我们对上面的代码稍作修改:

class Man:
    def __init__(self, name, gender, age):
        self.name = name
        self.gender = gender
        self.age = age

    def do_sports(self):
        self.take_meal()
        print(f"After that, {self.name} is going to do sports.")

    def take_meal(self):
        print(f"{self.name} is taking a meal.")


one_person = Man('王五', '男', '28')
one_person.do_sports()

输出内容如下:

王五 is taking a meal.
After that, 王五 is going to do sports.

逻辑也是比较清晰的,在do_sports()方法中,先调用了take_meal()方法,然后再打印方法本身的内容。

3.3 静态方法

“静态”一词翻译自“static”。所谓静态方法,指的就是某个方法是固定不变的,这里说的“不变”,是指该方法不受其所在类的其他属性和方法的影响。

考虑这样一个场景:王五吃晚饭要去做运动,但健身房在顶楼,他到达健身房需要乘坐电梯。如果用类来表现这个过程,结合前面的知识,代码可以写成下面的样子:

class Man:
    def __init__(self, name, gender, age):
        self.name = name
        self.gender = gender
        self.age = age

    def do_sports(self):
        print(f"{self.name} is going to do sports.")

    def take_meal(self):
        print(f"{self.name} has taken a meal and steps into the elevator.")

    def elevator_go_up(self):
        print("Elevator is going up...")
        # after some time...
        print("Elevator is on the top floor.")


one_person = Man('王五', '男', '28')
one_person.take_meal()
one_person.elevator_go_up()
one_person.do_sports()

输出内容如下:

王五 has taken a meal and steps into the elevator.
Elevator is going up...
Elevator is on the top floor.
王五 is going to do sports.

理解起来没有任何问题,但如果注意观察,会发现elevator_go_up这个方法和其他的方法不太一样:elevator_go_up中没有利用到类本身的其他属性和方法。

可以这样理解,elevator_go_up虽然定义在了Man这个类内,但实际上该方法没有使用任何类的信息。也就是说,Man这个类不会对elevator_go_up这个方法产生任何影响,所以我们说elevator_go_up方法是静态的。

尽管上述写法在语法上是没有问题的,但从功能上来说,elevator_go_up方法完全可以放到类外,作为一个函数来供Man中的方法调用。即改写成如下的形式:

class Man:
    def __init__(self, name, gender, age):
        self.name = name
        self.gender = gender
        self.age = age

    def do_sports(self):
        print(f"{self.name} is going to do sports.")

    def take_meal(self):
        print(f"{self.name} has taken a meal and step into the elevator.")


def elevator_go_up():
    print("Elevator is going up...")
    # after some time...
    print("Elevator is on the top floor.")

Note:
如果这样定义,那么就不能再用one_person.elevator_go_up()的方式调用这个函数了,因为该函数已经不再属于这个类了。

如果仍然想在类内定义该方法,那么对待此类静态的方法,需要加上一个修饰符:

class Man:
	...
	
	@staticmethod
	def elevator_go_up():
	    print("Elevator is going up...")
	    # after some time...
	    print("Elevator is on the top floor.")
	

调用方法是不变的。

关于修饰符
修饰符不是这篇文章的重点,读者可以将其按照字面意思进行理解:通过修饰符修饰的方法就具备了某些其他的特性。

前面说过,静态的意思是不依赖于类本身的其他信息,这意味着,即使不经过实例化,也能通过类名称直接调用该方法:

Man.elevator_go_up()

4. 总结

本文简答介绍了python中类的最基本、最常用的使用方法。关于类还有其他许多复杂的特性,这将在后续的文章中进行介绍。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

芳樽里的歌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值