Python3.8官网文档之类的基础语法阅读


Posted in Python onSeptember 04, 2021

官网类的基础语法阅读

英文官方文档: https://docs.python.org/3.8/tutorial/classes.html

中文官方文档: https://docs.python.org/zh-cn/3.8/tutorial/classes.html

类提供了一种组合数据和功能的方法。

创建一个新类意味着创建一个新的对象类型,从而允许创建一个该类型的新实例。

1、类定义

最简单的类定义看起来像这样:

class ClassName:
    <statement-1>
    .
    .
    .
    <statement-N>

类定义与函数定义 (def 语句) 一样必须被执行才会起作用。

当进入类定义时,将创建一个新的命名空间,并将其用作局部作用域。因此,所有对局部变量的赋值都是在这个新命名空间之内。 特别的,函数定义会绑定到这里的新函数名称。

2、类对象

类对象支持两种操作:属性引用和实例化。

(1)属性引用

属性引用的标准语法: obj.name

有效的属性名称是,类对象被创建时,存在于类命名空间中的所有名称。 因此,如果类定义是这样的:

class MyClass:
    """A simple example class"""
    i = 12345

    def f(self):
        return 'hello world'

那么 MyClass.iMyClass.f 就是有效的属性引用,将分别返回一个整数和一个函数对象。

类属性也可以被赋值,因此可以通过赋值来更改 MyClass.i 的值。

__doc__也是一个有效的属性,将返回所属类的文档字符串: "A simple example class"。

(2)实例化

类的实例化使用函数表示法。

可以把类对象视为是返回该类的一个新实例的不带参数的函数。 举例来说(假设使用上述的类):

x = MyClass()

创建类的新实例并将此对象分配给局部变量 x。

实例化操作(“调用”类对象)会创建一个空对象,也可以使用__init__() 创建带有特定初始状态的自定义实例。例如:

def __init__(self):
    self.data = []

此时,类的实例化操作会自动为新创建的类实例调用 __init__()。 因此在这个示例中,可以通过 x = MyClass() 语句获得一个经初始化的新实例:

__init__() 方法还可以有额外参数以实现更高灵活性。在这种情况下,提供给类实例化运算符的参数将被传递给 __init__()。 例如,:

>>> class Complex:
...     def __init__(self, realpart, imagpart):
...         self.r = realpart
...         self.i = imagpart
...
>>> x = Complex(3.0, -4.5)
>>> x.r, x.i
(3.0, -4.5)

3、实例对象

实例对象唯一操作是属性引用。 有两种有效的属性名称:数据属性和方法。

(1)数据属性

数据属性不需要声明,像局部变量一样,它们将在第一次被赋值时产生。

例如,如果 x 是上面创建的 MyClass 的实例,则以下代码段将打印数值 16,且不保留任何追踪信息:

x.counter = 1
while x.counter < 10:
    x.counter = x.counter * 2
print(x.counter)
del x.counter

(2)方法

方法是“从属于”对象的函数。 【注:方法是针对对象来说的,函数是针对类来说的】

(在 Python 中,方法这个术语并不是类实例所特有的:其他对象也可以有方法。例如,列表对象具有 append, insert, remove, sort 等方法。然而,在以下讨论中,我们使用方法一词将专指类实例对象的方法,除非另外显式地说明。)

实例对象的有效方法名称依赖于其所属的类。 【注:这里说的是方法名称】

根据定义,一个类中所有是函数对象的属性都是定义了其实例的相应方法。

因此在我们的示例中,x.f 是有效的方法引用,因为 MyClass.f 是一个函数,而 x.i 不是方法,因为 MyClass.i 不是一个函数。 但是x.f 与 MyClass.f 并不是一回事,它是一个方法对象,不是函数对象。

4、方法对象

通常,方法在绑定后立即被调用,在 MyClass 示例中,这将返回字符串 'hello world'。

x.f()

但是,立即调用一个方法并不是必须的: x.f 是一个方法对象,它可以被保存起来以后再调用。 例如:

xf = x.f
while True:
    print(xf())

将继续打印 hello world,直到结束。

虽然 f() 的函数定义指定了一个参数,但在上面调用 x.f() 时并没有带参数。 当不带参数地调用一个需要参数的函数时 Python 肯定会引发异常,即使参数实际未被使用。

方法的特殊之处就在于实例对象会作为函数的第一个参数被传入。 在我们的示例中,调用 x.f() 其实就相当于 MyClass.f(x)。 【注:也就是方法参数列表中的self】

总之,调用一个具有 n 个参数的方法就相当于调用再多一个参数的对应函数,这个参数值为方法所属实例对象,位置在其他参数之前。

当一个实例的非数据属性【注:即方法】被引用时,将搜索实例所属的类。

如果被引用的属性名称表示一个有效的类属性中的函数对象,会通过打包(指向)查找到的实例对象和函数对象 到一个抽象对象的方式来创建方法对象:这个抽象对象就是方法对象。 【注:xf = x.f,x.f 是一个方法对象】

当附带参数列表调用方法对象时,将基于实例对象和参数列表构建一个新的参数列表【注:self和参数列表】,并使用这个新参数列表调用相应的函数对象。

5、类和实例变量

一般来说,实例变量用于每个实例的唯一数据,而类变量用于类的所有实例共享的属性和方法:

【注:下例中kind是类变量,name是实例变量】

class Dog:

    kind = 'canine'         # class variable shared by all instances

    def __init__(self, name):
        self.name = name    # instance variable unique to each instance

>>> d = Dog('Fido')
>>> e = Dog('Buddy')
>>> d.kind                  # shared by all dogs
'canine'
>>> e.kind                  # shared by all dogs
'canine'
>>> d.name                  # unique to d
'Fido'
>>> e.name                  # unique to e
'Buddy'

正如 名称和对象 中已讨论过的,共享数据可能在涉及可变对象的时候,例如列表和字典,导致令人惊讶的结果。

例如以下代码中的 tricks 列表不应该被用作类变量,因为所有的 Dog 实例将只共享一个单独的列表:

【注:类变量是所有实例所共享的,以下代码中的 tricks 列表不应该被用作类变量,实例调用 add_trick 时,就改变了 tricks 列表】

class Dog:

    tricks = []             # mistaken use of a class variable

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

    def add_trick(self, trick):
        self.tricks.append(trick)

>>> d = Dog('Fido')
>>> e = Dog('Buddy')
>>> d.add_trick('roll over')
>>> e.add_trick('play dead')
>>> d.tricks                # unexpectedly shared by all dogs
['roll over', 'play dead']

正确的类设计应该使用实例变量:

class Dog:

    def __init__(self, name):
        self.name = name
        self.tricks = []    # creates a new empty list for each dog

    def add_trick(self, trick):
        self.tricks.append(trick)

>>> d = Dog('Fido')
>>> e = Dog('Buddy')
>>> d.add_trick('roll over')
>>> e.add_trick('play dead')
>>> d.tricks
['roll over']
>>> e.tricks
['play dead']

6、补充说明

如果同样的属性名称同时出现在实例和类中,则属性查找会优先选择实例:

>>>
>>> class Warehouse:
        purpose = 'storage'
        region = 'west'

>>> w1 = Warehouse()
>>> print(w1.purpose, w1.region)
storage west
>>> w2 = Warehouse()
>>> w2.region = 'east'
>>> print(w2.purpose, w2.region)
storage east

方法的第一个参数常常被命名为 self。 这也不过就是一个约定: self 这一名称在 Python 中绝对没有特殊含义。但是要注意,不遵循此约定会使得你的代码对其他 Python 程序员来说缺乏可读性,而且也可以想像一个 类浏览器 程序的编写可能会依赖于这样的约定。

任何一个作为类属性的函数都为该类的实例定义了一个相应方法。 函数定义的文本并非必须包含于类定义之内:将一个函数对象赋值给一个局部变量也是可以的。 例如:

# Function defined outside the class
def f1(self, x, y):
    return min(x, x+y)

class C:
    f = f1

    def g(self):
        return 'hello world'

    h = g

现在 f, g 和 h 都是 C 类的引用函数对象的属性,因而它们就都是 C 的实例的方法,其中 h 完全等同于 g。 但请注意,本示例的做法通常只会令程序的阅读者感到迷惑。

方法可以通过使用 self 参数的方法属性调用其他方法:

class Bag:
    def __init__(self):
        self.data = []

    def add(self, x):
        self.data.append(x)

    def addtwice(self, x):
        self.add(x)
        self.add(x)

方法可以通过与普通函数相同的方式引用全局名称。与方法相关联的全局作用域就是包含其定义的模块。(类永远不会被作为全局作用域。)

虽然我们很少会有充分的理由在方法中使用全局作用域,但全局作用域存在许多合法的使用场景:举个例子,导入到全局作用域的函数和模块可以被方法所使用,在其中定义的函数和类也一样。

通常,包含该方法的类本身是在全局作用域中定义的,而在下一节中我们将会发现为何方法需要引用其所属类的很好的理由。

每个值都是一个对象,因此具有 类(也称为 类型),并存储为 object.__class__

到此这篇关于Python3.8官网文档之类的基础语法阅读的文章就介绍到这了,更多相关python3.8基础语法内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
详解Python中time()方法的使用的教程
May 22 Python
Python实现简单的文件传输与MySQL备份的脚本分享
Jan 03 Python
python使用mysql数据库示例代码
May 21 Python
Python判断两个list是否是父子集关系的实例
May 04 Python
TensorFlow 滑动平均的示例代码
Jun 19 Python
python读取文本中的坐标方法
Oct 14 Python
django 连接数据库 sqlite的例子
Aug 14 Python
PyQt+socket实现远程操作服务器的方法示例
Aug 22 Python
python实现截取屏幕保存文件,删除N天前截图的例子
Aug 27 Python
python  logging日志打印过程解析
Oct 22 Python
Python pymysql模块安装并操作过程解析
Oct 13 Python
Python帮你解决手机qq微信内存占用太多问题
Feb 15 Python
python实现Nao机器人的单目测距
Sep 04 #Python
python读取mnist数据集方法案例详解
Sep 04 #Python
Pyqt5将多个类组合在一个界面显示的完整示例
Sep 04 #Python
一小时学会TensorFlow2之基本操作2实例代码
Python torch.flatten()函数案例详解
Aug 30 #Python
Python之基础函数案例详解
Aug 30 #Python
python中使用 unittest.TestCase单元测试的用例详解
Aug 30 #Python
You might like
世界第一个无线广播电台 KDKA
2021/03/01 无线电
中国站长站 For Dede4.0 采集规则
2007/05/27 PHP
PHP注释实例技巧
2008/10/03 PHP
php基本函数汇总
2015/07/09 PHP
php+ajax登录跳转登录实现思路
2016/07/31 PHP
php反序列化长度变化尾部字符串逃逸(0CTF-2016-piapiapia)
2020/02/15 PHP
bcastr2.0 通用的图片浏览器
2006/11/22 Javascript
javascript编程起步(第五课)
2007/01/10 Javascript
javascript拓展DOM操作 prependChild insertAfert
2010/11/17 Javascript
对jQuery的事件绑定的一些思考(补充)
2013/04/20 Javascript
将HTML格式的String转化为HTMLElement的实现方法
2014/08/07 Javascript
排序算法的javascript实现与讲解(99js手记)
2014/09/28 Javascript
jquery实现鼠标滑过小图时显示大图的方法
2015/01/14 Javascript
js省市联动效果完整实例代码
2015/12/09 Javascript
js实现简单的碰壁反弹效果
2016/08/30 Javascript
jQuery、layer实现弹出层的打开、关闭功能
2017/06/28 jQuery
详解ES6 Fetch API HTTP请求实用指南
2018/11/14 Javascript
ajax跨域访问遇到的问题及解决方案
2019/05/23 Javascript
javascript for循环性能测试示例
2019/08/07 Javascript
vue组件入门知识全梳理
2020/09/21 Javascript
Python实现的简单dns查询功能示例
2017/05/24 Python
python3.6连接MySQL和表的创建与删除实例代码
2017/12/28 Python
Pycharm配置远程调试的方法步骤
2018/12/17 Python
PyCharm设置每行最大长度限制的方法
2019/01/16 Python
利用python-docx模块写批量生日邀请函
2019/08/26 Python
python3连接mysql获取ansible动态inventory脚本
2020/01/19 Python
Django数据统计功能count()的使用
2020/11/30 Python
TALLY WEiJL法国网上商店:服装、时装及配饰
2019/08/31 全球购物
中国电子产品批发商/跨境电商/外贸网:Sunsky-online
2020/04/20 全球购物
西部世纪面试题
2014/12/05 面试题
残疾人创业典型事迹
2014/02/01 职场文书
意外伤害赔偿协议书
2014/09/16 职场文书
2015年学校团委工作总结
2015/05/26 职场文书
2015年依法治校工作总结
2015/07/27 职场文书
SpringBoot+Vue+JWT的前后端分离登录认证详细步骤
2021/09/25 Java/Android
JavaScript声明变量和数据类型的转换
2022/04/12 Javascript