收藏 分销(赏)

python开发之‘类’.pdf

上传人:曲**** 文档编号:226575 上传时间:2023-03-09 格式:PDF 页数:14 大小:1.12MB
下载 相关 举报
python开发之‘类’.pdf_第1页
第1页 / 共14页
python开发之‘类’.pdf_第2页
第2页 / 共14页
python开发之‘类’.pdf_第3页
第3页 / 共14页
python开发之‘类’.pdf_第4页
第4页 / 共14页
python开发之‘类’.pdf_第5页
第5页 / 共14页
点击查看更多>>
资源描述

1、Classes 类工Python在尽可能不增加新的语法和语义的情况下加入了类机制。这种机制是C+和Modula-3 的混合。Python中的类没有在用户和定义之间建立一个绝对的屏障,而是依赖于用户自觉的不 去“破坏定义”。然而,类机制最重要的功能都完整的保留下来:类继承机制允许多继承,派生 类可以覆盖(override)基类中的任 何方法,方法中可以调用基类中的同名方法。对象可以包 含任意数量的私有成员。用C+术语来讲,所有的类成员(包括数据成员)都是*公有*(参见Private Variables私有 变量)的,所有 的成员函数都是*虚*(virtual)的。没有特定的构造和析构函数。像Mo

2、dula-3 一样,在成员方法中没有什么简便的方式可以引用对象的成员:方法函数在定义时需要以引用 的对象做为第一个参数,调用时则会隐式引用对象。像Smalltalk 一样,类本身就是对象,在 更为广义的范围上理解:Python中一切数据类型都是对象。这样就形成了语义上的引入和重 命名。但是,像C+而非Modula-3中那样,大多数带有特殊语法的内置操作符(算法运算 符、下标等)都可以针对类的需要重新定义。A Word About Terminology 术语漫谈由于没有什么关于类的通用术语、我从Smalltalk和C+中借用一些(我更希望用Modula-3 的,因为它的面向对象机制比C+更接近

3、Python,不过我想没多少读者听说过它)。对象是被特化的,多个名字(在多个作用域中)可以绑定同一个对象。这相当于其它语言中的 别名。通常对Python的第一印象中会忽略这一点,使用那些不可变的基本类型(数值、字符 串、元组)时也可以很放心的忽视它。然而,在Python代码调用字典、链表之类可变对象,以及大多数涉及程序外部实体(文件、窗体等等)的类型时,这一语义就会有影响。这通用有 助于优化程序,因为别名的行为在某些方面类似于指针。例如,很容易传递一个对象,因为在 行为上只是传递了一个指针。如果函数修改了一个通过参数传递的对象,调用者可以接收到变 化一一在Pascal中这需要两个不同的参数传递

4、机制。Python Scopes and Name Spaces 作用域和命名空间在介绍类之前,我首先介绍一些有关Python作用域的规则:类的定义非常巧妙的运用了命名 空间,要完全理解接下来的知识,需要先理解作用域和命名空间的工作原理。另外,这一切的 知识对于任何高级Python程序员都非常有用。Lefs begin with some definitions.我们从一些定义开始。上命名空间*是从命名到对象的映射。当前命名空间主要是通过Python字典实现的,不过通常 示关心具体的实现方式(除非出于性能考虑),以后也有可能会改变其实现方式。以下有一些 命名空间的例子:内置命名(像absO这样

5、的函数,以及内置异常名)集,模块中的全局命名,函数调用中的局部命名。某种意义上讲对象的属性集也是个命名空间。关于命名空间需要了 解的一件很重要的事就是不同命名空间中的命名没有任何联系,例如两个不同的模块可能都会 定义一个名为“maximize”的函数而不 会发生混淆一一用户必须以模块名为前缀来引用它们。顺便提一句,我习惯称Python中任何一个之后的命名为*属性*-例如,表达式z.real中的real是对象z的一个属性。严格来讲,从模块中引用命名是引用属性:表达式modname.funcname中,modname是一个模块对象,funcname是它的一个属性。因此,模 块的属性和模块中的全局命

6、名有直接的映射关系:它们共享同一命名空间!#_ 属性可以是只读或可写的。后一种情况下,可以对属性赋值。你可以这样作:modname.the_answer=420可写的属性也可以用del语句删除。例如:delmodname.the answer 会从 modname 对象中删除 the answer 属性。在不同的时刻创建的命名空间,有不同的生存期。包含内置命名的命名空间在Python解释器 启动时创建,会一直保留,不被删除。模块的全局命名空间在模块定义被读入时创建,通常,模块命名空间也会一直保存到解释器退出。由解释器在最高层调用执行的语句,不管它是从脚 本文件中读入还是来自交互式输入,都是_掰

7、山_模块的一部分,所以它们也拥有自己的命名空间。(内置命名也同样被包含在一个模 块中,它被称作builtin o)当函数被丽时创蓬一个局部命名空间,函数反正返回过抛出一个未在函数内处理的异常时删 除。(实际上,说是遗忘更为贴切)。当然,每一个递归调用拥有自己的命名空间。上作用域*是Python程序中一个命名空间可以直接访问的正文区域。“直接访问”在这里的意思是 番找命名时无需引用命名前缀。尽管作用域是静态定义,在使用时他们都是动态的。每次执行时,至少有三个命名空间可以直 接访问的作用域嵌套在一起:包含局部命名的使用域在最里面,首先被搜索;其次搜索的是中 层的作用域,这里包含了同级的函数;最后搜

8、索最外面的作用域,它包含内置命名。如果一个命名声明为全局的,那么所有的赋值和引用都直接针对包含模全局命名的中级作用域。另外,从外部访问到的所有内层作用域的变量都是只读的。(试图写这样的变量只会在内部作 用域创建一个*新*局部变量,外部标示命名的那个变量不会改变)。从字面意义上讲,局部作用域引用当前函数的命名。在函数之外,局部作用域与全局使用域引 用同一命名空间:模块命名空间。类定义也是局部作用域中的另一个命名空间。重要的是作用域决定于源程序的文本:一个定义于某模块中的函数的全局作用域是该模块的命 名空间,而不是该函数的别名被定义或调用的位置,了解这一点非常重要。另一方面,命名的 实际搜索过程是

9、动态的,在运行时确定的然而,Python语言也在不断发展,以后有可能 会成为静态的“编译”时确定,所以不要依赖动态解析!(事实上,局部变量已经是静态确定了。)Python的一个特别之处在于其赋值操作总是在最里层的作用域。赋值不会复制数据只是将 命名绑定到对象。删除也是如此:“del x”只是从局部作用域的命名空间中删除命名x o事实 上,所有引入新命名的操作都作用于局部作用域。特别是import语句和函数定将模块名或函 数绑定于局部作用域。(可以使用global语句将变量引入到全局作用域。)关键字global可以用于从全局命名域引入个别变量并重绑定它;:keyword:o/oca/语句检索 外

10、围的作用域并进行重绑定。Scopes and Namespaces Example作用域和命名空间示例,以下示例演示了如何引用不同的作用域和命名空间,以及如何使用global和nonlocal影响变 量绑定:def scope_test():def do_local():spam=local spamdef do_nonlocal():nonlocal spamspam=nonlocal spamdef do_global():global spamspam=global spamspam=test spamdo_local()print(After local assignment:,spa

11、m)do_nonlocal()print(After nonlocal assignment:,spam)do_global()print(After global assignment:,spam)scope_test()print(ln global scope:,spam)The output of the example code is:示例代码输出如下:After local assignment:test spamAfter nonlocal assignment:nonlocal spamAfter global assignment:nonlocal spamIn global

12、 scope:global spam注意词部赋值(默认的)不会改变sope_test在spam上的绑定。nonlocal赋值改变了 scopejest在spam上的绑定,而global赋值改变了模块级绑定。You can also see that there was no previous binding for spam before the global assignment.你可以观察到没有进行global赋值之前spam上的绑定没有改变。A First Look at Classes 初识类RClasses introduce a little bit of new syntax,t

13、hree new object types,and some new semantics.类引入了一点新的语法,三种新的对象类型,以及一些新的语义。Class Definition Syntax 类定义语法工The simplest form of class definition looks like this:最简单的类定义形式如下:class ClassName:Class definitions,like function definitions(def statements)must be executed before they have any effect.(You could

14、 conceivably place a class definition in a branch of an if statement,or inside a function.)类的定义就像函数定义(:keyword:虑f语句),要先执行才能生效。(你当然可以把它放进if语 句的某一分支,或者一个函数的内部。)In practice,the statements inside a class definition will usually be function definitions,but other statements are allowed,and sometimes usefu

15、l well come back to this later.The function definitions inside a class normally have a peculiar form of argument list,dictated by the calling conventions for methods-again,this is explained later.习惯上,类定义语句的内容通常是函数定义,不过其它语句也可以,有时会很有用后面我 们再回过头来讨论。类中的函数定义通常包括了一个特殊形式的参数列表,用于方法调用约定 同样我们在后面讨论这些。When a cla

16、ss definition is entered,a new namespace is created,and used as the local scope-thus,all assignments to local variables go into this new namespace.In particular,function definitions bind the name of the new function here.进入类定义后,会创建一个新的命名空间,就像使用一个局部使用域一一因此,所有对局部变 量的赋值 都会处于这个新的命名空间。此时函数定义绑定这这里的新函数名上。W

17、hen a class definition is left normally(via the end),a class object is created.This is basically a wrapper around the contents of the namespace created by the class definition;weUl learn more about class objects in the next section.The original local scope(the one in effect just before the class def

18、inition was entered)is reinstated,and the class object is bound here to the class name given in the class definition header(ClassName in the example).类定义完成时(正常退出),就创建了一个类对象。基本上它是对类定义创建的命名空间进行 了一个包装;我们在下一节进一步学习类对象的知识。原始的局部作用域(类定义引入之前生 效的那个)得到恢复,类对象在这里绑定到类定义头部的类名(例子中是ClassName)。Class Objects类对象工Class

19、objects support two kinds of operations:attribute references and instantiation.类对象支持两种操作:属性引用和实例化。Attribute references use the standard syntax used for all attribute references in Python:obj.name.Valid attribute names are all the names that were in the classs namespace when the class object was crea

20、ted.So,if the class definition looked like this:*属性引用*使用和Python中所有的属性引用一样的标准语法:obj.name、。类对象创建后,类命名空间中所有的命名都是有效属性名。所以如果类定义是这样:class MyClass:A simple example classi=12345def f(self):return hello worldthen MyClass.i and MyClass.f are valid attribute references,returning an integer and a function objec

21、t,respectively.Class attributes can also be assigned to,so you can change the value of MyClass.i by assignment._doc_ is also a valid attribute,returning the docstring belonging to the class:A simple example class.那么MyClass.i和MyClass.f是有效的属性引用,分别返回一个整数和一个方法对象。也可 以对类属性赋值,你可以通过给MyClass.i赋值来修改它。_doc_也是一

22、个有效的属性,返回类的文档字符串:“A simple example class”。Class instantiation uses function notation.Just pretend that the class object is a parameterless function that returns a new instance of the class.For example(assuming the above class):类的实例化使用函数符号。只要将类对象看作是一个返回新的类实例的无参数函数即可。例如(假设沿用前面的类):x=MyClass()creates a

23、new instance of the class and assigns this object to the local variable x.以上创建了一个新的类*实例*并将该对象赋给局部变量二X、。The instantiation operation(calling“a class object)creates an empty object.Many classes like to create objects with instances customized to a specific initial state.Therefore a class may define a s

24、pecial method named init(),like this:这个实例化操作(“调用”一个类对象)来创建一个空的对象。很多类都倾向于将对象创建为有 初始状态的。因此类可能会定义一个名为init()的特殊方法,像下面这样:def_init_(self):self.data=When a class defines an init()method,class instantiation automatically invokes init()for the newly-created class instance.So in this example,a new,initialized

25、 instance can be obtained by:类定义了 init()方法的话,类的实例化操作会自动为新创建的类实例调用 nit_()方法。所以在下例中,可以这样创建一个新的实例:x=MyClassQOf course,the init()method may have arguments for greater flexibility.In that case,arguments given to the class instantiation operator are passed on to init 0.For example,当然,出于灵活的需要,init()方法可以有参数

26、。事实上,参数通过 init()传递到类的实例化操作上。例如:class Complex:.def _init_(self,realpart,imagpart):.self.r=realpart.self.i=imagpartx=Complex(3.0,-4.5)x.r,x.i(3.0,-4.5)Instance Objects实例对象Now what can we do with instance objects?The only operations understood by instance objects are attribute references.There are two

27、kinds of valid attribute names,data attributes and methods.现在我们可以用实例对象作什么?实例对象唯一可用的操作就是属性引用。有两种有效的属性 名。data attributes correspond to instance variables in Smalltalk,and to“data members in C+.Data attributes need not be declared;like local variables,they spring into existence when they are first assi

28、gned to.For example,if x is the instance of MyClass created above,the following piece of code will print the value 16,without leaving a trace:*数据属性*相当于Smalltalk中的“实例变量”或C+中的“数据成员”。和局部变量一样,数据 属性不需要声明,第一次使用时它们就会生成。例如,如果x是前面创建的:class:,MyClass实 例,下面这段代码会打印出16而不会有任何多余的残留:x.counter=1 while x.counter 10:x.

29、counter=x.counter*2print(x.counter)del x.counterThe other kind of instance attribute reference is a method.A method is a function that belongs to”an object.(In Python,the term method is not unique to class instances:other object types can have methods as well.For example,list objects have methods ca

30、lled append,insert,remove,sort,and so on.However,in the following discussion,well use the term method exclusively to mean methods of class instance objects,unless explicitly stated otherwise.)另一种引用属性是*方法*。方法是“属于一个对象的函数。(在Python中,方法不止是类实 例所独有:其它类型的对象也可有方法。例如,链表对象有append,insert,remove,sort等等 方法。然而,在后面

31、的介绍中,除非特别说明,我们提到的方法特指类方法)Valid method names of an instance object depend on its class.By definition,all attributes of a class that are function objects define corresponding methods of its instances.So in our example,x.f is a valid method reference,since MyClass.f is a function,but x.i is not,since M

32、yClass.i is not.But x.f is not the same thing as MyClass.f it is a method object,not a function object.实例对象的有效名称依赖于它的类。按照定义,类中所有(用户定义)的函数对象对应它的实 例中的方法。所以在我们的例子中,x.f是一个有效的方法引用,因为MyClass.f是一个函数。但x.i不是,因为MyClass.i是不是函数。不过x.f和MyClass.f不同 它是一个方法对象,不是一个函数对象。Method Objects方法对象Usually,a method is called rig

33、ht after it is bound:通常,方法通过右绑定调用:x.f()In the MyClass example,this will return the string hello world.However,it is not necessary to call a method right away:x.f is a method object,and can be stored away and called at a later time.For example:在MyClass示例中,这会返回字符串hello world。然而,也不是一定要直接调用方法。x.f是 一个方法对

34、象,它可以存储起来以后调用。例如:xf=x.f while True:print(xf()will continue to print hello world until the end of time.会不断的打印“hello world”。What exactly happens when a method is called?You may have noticed that x.f()was called without an argument above,even though the function definition for f()specified an argument.

35、What happened to the argument?Surely Python raises an exception when a function that requires an argument is called without any even if the argument isnt actually used.调用方法时发生了什么?你可能注意到调用x.f()时没有引用前面标出的变量,尽管在f()的 函数定义中指明了一个参数。这个参数怎么了?事实上如果函数调用中缺少参数,Python会抛 出异常一一甚至这个参数实际上没什么用Actually,you may have gu

36、essed the answer:the special thing about methods is that the object is passed as the first argument of the function.In our example,the call x.f()is exactly equivalent to MyClass.f(x).In general,calling a method with a list of n arguments is equivalent to calling the corresponding function with an ar

37、gument list that is created by inserting the methods object before the first argument.实际上,你可能已经猜到了答案:方法的特别之处在于实例对象作为函数的第一个参数传给了 函数。在我们的例子中,调用x.f相当于MyClass.f(x)o通常,以个参数的列表去调用一 个方法就相当于将方法的对象插入到参数列表的最前面后,以这个列表去调用相应的函数。If you still dont understand how methods work,a look at the implementation can perhap

38、s clarify matters.When an instance attribute is referenced that isnt a data attribute,its class is searched.If the name denotes a valid class attribute that is a function object,a method object is created by packing(pointers to)the instance object and the function object just found together in an ab

39、stract object:this is the method object.When the method object is called with an argument list,it is unpacked again,a new argument list is constructed from the instance object and the original argument list,and the function object is called with this new argument list.如果你还是不理解方法的工作原理,了解一下它的实现也许有帮助。引

40、用非数据属性的实例属 性时,会搜索它的类。如果这个命名确认为一个有效的函数对象类属性,就会将实例对象和函 数对象封装进一个抽象对象:这就是方法对象。以一个参数列表调用方法对象时,它被重新拆 封,用实例对象和原始的参数列表构造一个新的参数列表,然后函数对象调用这个新的参数列 表。Random Remarks 一些说明Data attributes override method attributes with the same name;to avoid accidental name conflicts,which may cause hard-to-find bugs in large pr

41、ograms,it is wise to use some kind of convention that minimizes the chance of conflicts.Possible conventions include capitalizing method names,prefixing data attribute names with a small unique string(perhaps just an underscore),or using verbs for methods and nouns fbr data attributes.同名的数据属性会覆盖方法属性

42、,为了避免可能的命名冲突一一这在大型程序中可能会导致难 以发现的bug 一最好以某种命名约定来避免冲突。可选的约定包括方法的首字母大写,数据 属性名前缀小写(可能只是一个下划线),或者方法使用动词而数据属性使用名词。Data attributes may be referenced by methods as well as by ordinary users(clients)of an object.In other words,classes are not usable to implement pure abstract data types.In fact,nothing in Py

43、thon makes it possible to enforce data hiding it is all based upon convention.(On the other hand,the Python implementation,written in C,can completely hide implementation details and control access to an object if necessary;this can be used by extensions to Python written in C.)数据属性可以由方法引用,也可以由普通用户(

44、客户)调用。换句话说,类不能实现纯的数据 类型。事实上Python中没有什么办法可以强制隐藏数据-切都基本约定的惯例。(另一方法讲,Python的实现是用C写成的,如果有必要,可以用C来编写Python扩展,完全隐 藏实现的细节,控制对象的访问。)Clients should use data attributes with care clients may mess up invariants maintained by the methods by stamping on their data attributes.Note that clients may add data attrib

45、utes of their own to an instance object without affecting the validity of the methods,as long as name conflicts are avoided 一 again,a naming convention can save a lot of headaches here.客户应该小心使用数据属性一一客户可能会因为随意修改数据属性而破坏了本来由方法维护的 数据一致性。需要注意的是,客户只要注意避免命名冲突,就可以随意向实例中添加数据属性 而不会影响方法的有效性一一再次强调,命名约定可以省去很多麻烦。

46、There is no shorthand for referencing data attributes(or other methods!)from within methods.I find that this actually increases the readability of methods:there is no chance of confusing local variables and instance variables when glancing through a method.从方法内部引用数据属性(或者方法!)没有什么快捷的方式。我认为这事实上增加了方法的 可

47、读性:即使粗略的浏览一个方法,也不会有混淆局部变量和实例变量的机会。Often,the first argument of a method is called self.This is nothing more than a convention:the name self has absolutely no special meaning to Python.(Note,however,that by not following the convention your code may be less readable to other Python programmers,and it

48、is also conceivable that a class browser program might be written that relies upon such a convention.)通常方法的第一个参数命名为self o这仅仅是一个约定:对Python而言,self,绝对没有任 何特殊含义。(然而要注意的是,如果不遵守这个约定,别的Python程序员阅读你的代码时 会有不便,而且有些*类浏览器*程序也是遵循此约定开发的。)Any function object that is a class attribute defines a method for instances

49、 of that class.It is not necessary that the function definition is textually enclosed in the class definition:assigning a function object to a local variable in the class is also ok.For example:类属性中的任何函数对象在类实例中都定义为方法。不是必须要将函数定义代码写进类定义中,也可以将一个函数对象赋给类中的一个变量。例如:#Function defined outside the classdef fl

50、(self,x,y):return min(x,x+y)class C:f=fldef g(self):return hello worldh=gNow f,g and h are all attributes of class C that refer to function objects,and consequently they are all methods of instances of C-h being exactly equivalent to g.Note that this practice usually only serves to confuse the reade

展开阅读全文
相似文档                                   自信AI助手自信AI助手
猜你喜欢                                   自信AI导航自信AI导航
搜索标签

当前位置:首页 > 通信科技 > 开发语言

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        获赠5币

©2010-2024 宁波自信网络信息技术有限公司  版权所有

客服电话:4008-655-100  投诉/维权电话:4009-655-100

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :gzh.png    weibo.png    LOFTER.png 

客服