codeye
2022/10/14阅读:43主题:默认主题
犯罪现场
以简单的方式解释Python类 利用实例了解类的基本原理
当我第一次学习Python类的时候,我发现它真的很复杂,我没有掌握为什么需要了解它们的原因。在大学的一节课上,教授开始直接解释建立类的语法,而没有解释做这个特定主题的真正意义,并使用了非常无聊的例子,使我迷失了方向。
在这篇文章中,我想用一种不同的方式来解释Python类。我将开始解释为什么需要知道这些类,并展示一些已经建成的类的许多案例。一旦外部环境清楚了,下一步就是用一些例子和插图一步一步地展示如何定义类。
目录
类的介绍
创建一个类
构造函数方法
魔法
实例方法
-
类的介绍 当你开始学习Python时,你肯定遇到过这样一句话。
Python是一种面向对象的编程语言
这意味着用Python编程会导致到处被对象包围。在
我们给一个变量赋值,就是在创建一个对象。这个对象属于一个已经预先建立的特定类别,像数字、字符串、列表、字典等等。根据不同的类,该对象将有不同的属性和方法。

让我们看看一些对象和类的经典例子。
a = 28
print(type(a))
#<class 'int'>
我们定义了一个对象a,它属于Integer类。
ls = [1,2,3]
print(type(ls))
#<class 'list'>
这一次,新的对象属于List类。从这个对象中,我们可以调用已经在 Python 中预先建立的方法。为了看到对象中允许的所有方法,我们使用 dir
函数。
dir(l)
从输出结果中,我们可以注意到这个类可以提供三种类型的方法。
初始化方法__init__
,以这种方式调用是因为它是初始化对象属性的方法。此外,一旦对象被创建,它就会被自动调用。
魔法
是两边有双下划线的特殊方法。例如,__add__
和__mul__
分别用来对同一类别的对象进行求和和乘法,而__repr__
则返回对象的一个字符串表示。
实例方法是属于创建的对象的方法。例如,
ls.append(4)
在列表的末尾添加一个元素。
-
创建一个类
现在,我们将创建一个空的类,我们将在教程中逐步添加部分代码。
class Dog:
pass
我们创建了一个名字为Dog的类,其中pass用来表示没有定义任何东西。
jack = Dog()
print(type(jack))
#<类 '__main__.Dog'> >
一旦我们定义了Dog类,我们就可以创建一个该类的对象,它被分配给变量jack。它是用我们用来调用一个函数的类似符号建立的。Dog()
这个对象也可以被称为实例。如果你发现某个地方写着 "instance "或 "object",不要感到困惑,它们总是指同一事物。
像以前一样,我们检查对象的类型。输出结果清楚地指出,该对象属于狗类。
-
初始化方法
除了前面显示的代码外,初始化方法__init__被用来初始化Dog类的属性。
class Dog:
def __init__(self,name,breed,age):
self.Name = name
self.Breed = breed
self.Age = age
print("Name: {}, Breed: {}, Age: {}".format(self.Name,
self.Breed,self.Age))
我们可以观察到,该方法有不同的参数。
self
是作为第一个参数使用的标准符号,指的是对象,稍后将被创建。它对于访问属于该类的属性也很有用。
name
、breed
和age
是其余的参数。每个参数都是用来存储对象的特定属性值的。
名称、品种和年龄是定义的属性。注意这些属性通常不大写。在这篇文章中,它们是大写的,以突出属性和它们相应的值之间的区别。
jack = Dog('Jack','Husky',5)
#名字: Jack, 品种: Husky, 年龄: 5
print(jack)
#<__main__.Dog对象在0x000002551DCEFFD0>处
print(jack.Age)
#5
我们再次创建了这个对象,但是我们也指定了与属性相对应的值。如果你尝试运行这段代码,你会自动获得灰色窗口第二行中显示的文本。这是一个检查所定义的类是否运行良好的好方法。
同样值得注意的是,初始化方法在创建对象后被自动调用。这方面可以通过打印属性 "Age
"的值来证明。你可以对其余的属性做同样的事情。
-
神奇的方法
也有可能以一种更复杂的方式来打印相同的信息。为了这个目的,我们使用神奇的方法__repr__
。
class Dog:
def __init__(self,name,breed,age):
self.Name = name
self.Breed = breed
self.Age = age
def __repr__(self):
return "Name: {}, Breed: {}, Age: {}".format(self.Name,
self.Breed,self.Age)
方法 __repr__
需要一个唯一的参数 selffrom
,它可以访问对象的属性。
jack = Dog('Jack','Husky',5)
print(jack)
#Name: Jack, Breed: Husky, Age: 5
#名字。Jack, 品种: Husky, 年龄: 5
如果我们显示创建的新实例,我们可以查看属性和它们各自的值。
-
实例方法

睡觉还是醒着?
实例方法是属于类的方法。作为神奇的方法,它们接受一个输入参数self来访问类的属性。让我们看一个例子。
class Dog:
def __init__(self,name,breed,age,tired):
self.Name = name
self.Breed = breed
self.Age = age
self.Tired = tired
def __repr__(self):
return "Name: {}, Breed: {}, Age: {}".format(self.Name,
self.Breed,self.Age)
def Sleep(self):
if self.Tired==True:
return 'I will sleep'
else:
return "I don't want to sleep"
在初始化方法中,我们添加了一个新的参数tired
,因此也添加了一个新的属性Tired
。之后,我们定义了一个名为Sleep
的新方法:如果该属性的值等于True
,狗就会睡觉,否则就不会。
jack = Dog('Jack','Husky',5,tired=False)
print(jack.Sleep())
#我不想睡觉 这只狗不累,所以它不会睡觉。
最后的想法。
在这篇文章中,我对Python类进行了快速总结。我希望你能发现它对巩固你关于类的基础很有用。我没有解释其他类型的方法,静态方法和类方法,因为我想专注于最常见的方法。此外,另一个有趣的话题是类的继承性。
#2 实用的 Python类与实例变量
如何定义它们并与之互动
类是Python中最基本的一块,因为它是面向对象编程的本质。
Python中的所有东西都是一个对象,如整数、列表、字典、函数等等。每个对象都有一个类型,对象类型是用类来创建的。
实例是属于一个类的对象。例如,列表是 Python 中的一个类。当我们创建一个列表时,我们有一个列表类的实例。
在这篇文章中,我将集中讨论类和实例变量。我假设你对 Python 中的类有基本了解。如果没有,你仍然可以理解什么是类和实例变量,但其语法可能看起来有点让人不知所措。
如果你想了解基础知识,我也写过一篇关于Python类的介绍性文章。
我们先来看看类和实例变量。
类变量是在类内声明的,但在任何函数之外。实例变量是在构造函数中声明的,也就是__init__method。
考虑一下下面的类定义。
class Book():
fontsize = 9
page_width = 15
def __init__(self, name, writer, length):
self.name = name
self.writer = writer
self.length = length
假设图书类是由一个出版公司使用的。字体大小和页宽是类的变量。创建的每一个图书实例的字体大小为9,页宽为15厘米。
name
、writer
和length变量是在__init__方
法中声明的,所以它们是实例变量。这些变量的值是在创建一个实例时确定的。
这是有道理的,因为字体大小和页面宽度通常是标准的。然而,名字、作者和长度是针对每本书(即实例)的。
将字体大小和页宽作为类变量来声明,可以节省我们很多时间和精力。假设出版公司决定改变书中使用的字体大小。如果它是一个实例变量,我们将需要为每个实例(即书)改变它。然而,由于它是一个类变量,一次赋值就可以完成每本书的工作。
让我们创建一个书类的实例。
book1 = Book("Intro to Python", "John Doe", 50000)
print(book1.writer)
"John Doe"
print(book1.page_width)
15
尽管我们没有明确地将page_width
变量分配给我们的实例,但它默认有这个属性。
我们可以为任何实例改变类变量的值(即覆盖它们)。假设我们想让book1更宽一点,所以我们将改变这个实例的page_width
。
book1.page_width = 17
print(book1.page_width)
17
print(Book.page_width)
15
正如你所看到的,我们只改变了book1实例的值。类变量的值保持不变。
我们定义的方法可以访问类的变量,但是我们需要小心。我将在下面的例子中告诉你原因。
我们为Book类定义一个方法,根据长度(字数)、字体大小和页宽来计算页数。
def number_of_pages(self): pages = (self.length * fontsize) / (page_width * 100) 返回页数
这个方法会引发一个NameError,说'fontsize'没有被定义。page_width
"也是如此。虽然这些是类变量,但我们需要告诉方法从哪里获得它们。
我们可以从实例本身或从类中获取它们。
#使用实例
def number_of_pages(self):
pages = (self.length * fontsize) / (page_width * 100)
return pages
#使用该类
def number_of_pages(self):
pages = (self.length * self.fontsize) / (self.page_width * 100)
return pages
这两种方法都可以工作。让我们来做一个例子。
book1 = Book("Intro to Python", "John Doe", 50000) book1_pages = book1.number_of_pages() print(book1_pages) 300 更新类的变量将影响该类的所有实例。这是一个很好的功能,可以为我们节省时间和精力。然而,我们也需要注意变化的程度。
下面是一个例子。
book1 = Book("Intro to Python", "John Doe", 50000)
book2 = Book("Pandas介绍", "Jane Doe", 40000)
print(book1.fontsize, book2.fontsize)
(9, 9)
book.fontsize = 11
print(book1.fontsize, book2.fontsize)
(11, 11)
实例通过它们所属的类访问类的变量。让我们做一个例子来说明我的意思。
__dict__
方法可以用来查看一个实例或类的属性。
book1 = Book("Intro to Python", "John Doe", 50000)
print(book1.__dict__)
{'name': 'Intro to Python', 'writer': 'John Doe', 'length': 50000}
print(book1.fontsize)
9
当我们打印出book1的数据属性时,我们没有看到字体大小和页宽。然而,我们可以通过打印出来看到book1有fontsize
属性。
实例(book1)通过类访问了类的变量。让我们也在Book类上应用__dict__
方法。 实例(book1)通过类访问了类的变量。让我们也在Book类上应用__dict__方法。
print(Book.__dict__)
'__module__': '__main__', 'fontsize': 9,
'page_width': 15,
'__init__': <function Book.__init__ at 0x7f6cc5f54620>,
'number_of_pages': <function Book.number_of_pages at 0x7f6cc5f548c8>,
'__dict__': <attribute '__dict__' of 'Book' objects>,
'__weakref__': <attribute '__weakref__' of 'Book' objects>, '__doc__': None}
类的变量以及方法和其他一些东西被打印出来。
结论 类变量会影响整个类。因此,当一个类变量被更新时,所有的实例都被更新。这很方便,但我们也需要小心。如果不小心使用,可能会发生不希望发生的后果。
实例变量对每个实例都有唯一的值。我们在创建实例时为它们赋值。
所有的实例在一开始都采取相同的类变量值,但我们可以在以后为一个实例更新它们。我们对一个实例所做的改变不会影响其他实例的类变量值。
#3 一个犯罪现场被发现,在证据中,有一份代理人的名单,没有明显的联系。
你在记录部门的工作是将这份名单与警方的记录进行比对,找到一个完全匹配的名单。
你的函数将收到一个列表作为第一个参数,即被盗记录,然后是一个列表,即数据库。
只有在包含相同顺序的相同名字的情况下才会找到匹配,不多不少。如果第一个参数是一个空列表,你的代码应该返回 None。
数据库将总是包含不止一个列表。匹配应该返回 "找到匹配"。如果没有找到匹配,你的代码应该返回 "没有匹配"。
例子:
agents(["John", "Sarah"],
[["John", "Sarah"], ["Mary", "David"])
== "找到匹配的"
你作为警局的首席技术骨干,任务是建立辖区内的住户画像,包括姓名、性别、年龄、身高体重等自然人属性;
同时,也要留出扩展的灵活性。添加、籍贯、国籍、工作、信仰等社会属性;
结合下面两篇文章学习SQL,我们思考如何建立数据库并且设计编码为何用到面向对象的编程OOP方法比如:class
满足既可以通过姓名,查询姓名为关键词; 也可以通过年龄段、身高等等数值范围查询结果满足所有符合的人群;
作者介绍