英语语法基础知识大全问题 承担——行为,对吗?

从语法角度分析公文中的不规范现象

公文是处理公务,进行的重要工具。公文的现实作用与特点要求其表述必须严谨规范,准确无误。然而,具体过程中存在不少违反语法规范的现象。综合来看,公文中常见的语法错误主要有以下几种。
  在汉语的句法成分中,主语(中心语)与谓语(中心语),动语与宾语(中心语),定语、状语、补语与其中心语,都是一对对相互搭配的成分。所谓的搭配不当,一般情况下,是指这些相互搭配的成分在语义上不能贯通。
  【例1】深刻分析新形势下争取群众路线的有效方法是要树立正确的权力观、政绩观、利益观。
  此例的问题是动语和宾语搭配不当。“争取群众路线的有效方法”是一个动宾短语作定语的定中短语,其中的“争取”和“群众路线”搭配成动宾短语。从词义来看,这种搭配是不合理的,宜改为“践行群众路线的有效方法”。
  【例2】党代表认真热心的态度受到来访群众的好评。
  此例的问题是定语与其中心语搭配不当。在汉语结构中,短语是“语义上能逐层贯通和结构上都能逐层搭配起来的没有句调的一组词”,其中语义的贯通起着决定性作用。定语“热心”是有热情、有兴趣、肯尽力的意思,在语义上与中心语“态度”无法搭配。此例可修改为“党代表态度认真热情,受到来访群众的好评”。
  【例3】我们要善于发现本文由联盟收集整理和中的和问题。
  此例是多个动语搭配多个宾语,其问题主要是动语与宾语位置不对应导致搭配不当。可将“经验”与“问题”对换位置,或者修改为“我们要善于在工作中发现问题和总结经验”。
  此外,公文中还有中补、状中、主宾、介宾等搭配不当的现象。
  句法成分残缺不全,是指不符合隐含、省略的条件而缺少应有的句法成分。在汉语中,句法成分往往是一对对相互搭配出现的。一般而言,这一对对的成分,出现一个,与它相匹配的另一个就必须出现。否则,就会造成句法结构的不完整,表达的句义不正确,甚至导致句子不能成立。
  【例4】走访群众、企业次数不够的干部要被扣奖金,排名较后的干部要被约谈,并作为年终奖惩以及干部选拔的参考依据。
  句中“要被扣奖金”和“要被约谈”的主语都是“干部”,是“人”;而“作为年终奖惩以及干部选拔参考的依据”的主语应该是“事”,即某个标准或记录。前两句与第三句的陈述对象不一致,因而造成第三句缺少主语。综合来看,此例可修改为“走访群众、企业次数不够的干部要被扣奖金,排名较后的干部要被约谈,并记录在案,作为年终奖惩以及干部选拔的参考依据”。
  此外,公文中还有谓语、宾语、定语、状语、补语等成分残缺的现象。
  句法成分多余累赘是指已经出现的成分或不该出现的成分,重复出现或强制使用,以致结构不合法,语义啰唆甚至不合逻辑。
  【例5】本次谈话紧扣作风建设,聚焦反对“四风”,并结合民生事业建设等方面,谈话直奔主题,谈话问题毫不回避。
  首先,此例的最后一句“谈话问题毫不回避”语序不当,宜改为“谈话毫不回避问题”。这样,则“谈话直奔主题”和“谈话毫不回避问题”的主语“谈话”多余,因为它作为全句的主语已经在第一分句中出现,并且可以贯通所有分句,没有必要在后续分句中重复出现。另外,“结合”与“方面”搭配不当。综合来看,此例可修改为“本次谈话紧扣作风建设,聚焦反对‘四风’,并结合民生事业建设等方面情况,直奔主题,毫不回避问题”。
  【例6】市督导组充分肯定南区开展党的群众路线活动的前期工作部署,并强调四点工作意见:一是尽快成立工作领导小组及下设机构,建立实践活动工作责任制;二是马上动员、落实工作,做到了“规定动作”不走样、“自选动作”有特色;三是把握实施进度,加强与市督导组的沟通协调,及时汇报情况;四是规范整理信息素材,总结实践经验,提高理论及实践水平。
  从句子意思来看,市督导组强调的四点工作意见是希望南区努力做到的,而不是南区已经做到的。此例中的“做到了‘规定动作’不走样、‘自选动作’有特色”,因为多了助词“了”,使未完成的动作变成了已完成的动作,所以这一句宜改为“做到‘规定动作’不走样、‘自选动作’有特色”。
  此外,公文中还有谓语、宾语、定语、状语、补语等成分多余的现象。
  句法成分语序有误是指一些相搭配的句法成分颠倒应有的语序,或者将某些句法成分置于其他句法成分的位置上,以致结构不合法,语义模糊或不合逻辑。
  【例7】团工委、党政办、人事办、公安分局、司法所、流管办、个私协、卫计局、

}

作者:开酱 来源:沪江教研 06:30

对于日语学习者而言,复合动词的用法是一大难点,尤其是意思上比较接近的复合动词,在使用时很难区分。比如“~ぬく”“~とおす”“~つくす”“~きる”均可以表示“行为的完了”,但是他们都有各自的特点和使用规则。那该如何区分这几个复合动词呢,下面就为大家讲解一下。

“~ぬく”“~とおす”“~つくす”“~きる”在意义上都可以表示“完了”,它们之间有时可以相互替换,但也有不能相互替换的情况。

含有在持续性的行为过程中或多或少存在着一些障碍或苦难,但会克服障碍或困难,直至最后从中摆脱出来的意思。

例:苦しかったが最後まで走りぬいた。

强调状态或行为无间断、稳定不变地持续着的过程。含有使某一状态维持下去的恒常性。与“~ぬく”的区别是“未必是追求有成果、结果”。

例:50年間【隠しとおした/*隠しぬいた】秘密を初めて他人に打ち明ける。

意味着持续进行着某一行为,直至达到极限的程度。这点与“~ぬく”很相似,但是“~つくす”含有在规定的范围或数值前提下,“丧失全部,什么也没剩下”、“由有变成零”的意思,而“~ぬく”没有这层含义。

例:そしてその微生物がそこでよく育つと、やがてシェ―レーの中一杯になって、栄養も【使いつくして/*使いぬいて】死んでしまう。

强调最后的状态变化,一般不考虑中间过程或经过。在表示“最后的状态变化”这点上与“~つくす”接近,但“~つくす”还注重过程,包含多数的东西慢慢减少着变化的意思。

例:みんな【疲れきた/*疲れつくした】顔だね、どうした?

想查看更多日语学习文章可扫下方二维码关注沪江日语教研↓

本内容为沪江日语教研原创,未经授权严禁转载。

}

还没有系统学习语法,这是我选择的系统学习语法的书。因为之前已经看过4本python的书。在摘抄的时候,过于基本的就不写了。做为一个vim党,idle之类的内容我都略过了。

这是我目前为止看过内容最丰富的python书。以”,b’axolc’

类型、None、布尔值

ps:虽然我们有时候会用typy,isinstance等判断对象的类型,但是最好不要滥用,因为这样限制了对象的使用,因而也破坏了代码的灵活性,写出来的代码,也就不够’pythonic’

Python数字类型的完整工具包括:

第22章 模块代码编写基础

import使一个变量名引用整个模块对象,我们必须通过模块名称来得到该模块的属性(例如,'#由于类B并没有设置__slots__,__dict__属性是可用的。并不会因为超类A而对实例对象b产生影响。

要使slots真正起作用,必须子类和超类都有slots属性。

有一种称为特性(property)的机制,提供另一种方式让新式类定义自动调用的方法,来读取或赋值实例属性。他是__getattr____setattr__重载方法的替代做法。

特性的产生是以三种方法(获得、设置以及删除运算的处理器)以及通过文档字符串调用内置函数property。如果任何参数以None传递或省略,该运算就不能支持。特性一般都是在class语句顶层赋值。

age的获取就会自动调用getage方法。

除了特性和运算符重载方法,Python支持属性描述符的概念–带有__get____set__方法的类,分配给类属性并且由实例继承,这拦截了对特定属性的读取和写入访问。

元类是子类化了type对象并且拦截类创建调用的类。此外,它们还为管理和扩展类对象提供了一种定义良好的钩子。

静态方法–嵌套在一个类中的没有self参数的简单函数,并且旨在操作类属性而不是实例属性。静态方法不会接受一个自动的self参数,不管是通过一个类还是一个实例调用。

类方法–类的一种方法,传递给它们的第一个参数是一个类对象而不是一个实例,不管是通过一个实例或一个类调用它们。即便是通过一个实例调用,这样的方法也可以通过它们的self类参数来访问类数据。

2.6和3.0中的静态方法:

  • 在Python2.6中,我们必须总是把一个方法声明为静态的,从而不带一个实例而调用它,不管是通过一个类或一个实例调用它。。不声明的话,就是未绑定方法,未绑定方法需要传入一个实例对象。
  • 在Python3.0中,如果方法只通过一个类调用的话,我们不需要将这样的方法声明为静态的,但是,要通过一个实例调用它,我们必须这么做。

2.x中的静态方法和类方法。


使用静态方法内置函数,我们的代码现在允许在Python2.6和Python3.0中通过类或其任何实例来调用无self方法:(如果不使用静态方法内置函数,Pyhton2.6不管是通过类还是实例,都无法调用无self方法,Python3.0则只允许通过类调用无self实例方法)

使用类方法统计每个类的实例
实际上,由于类方法总是接收一个实例树中的最低类:

  • 静态方法和显式类名称可能对于处理一个类本地的数据来说是更好的解决方案。
  • 类方法 可能更适合 处理对层级中的每个类不同的数据。

装饰器和元类:第一部分
从语法上来讲,函数装饰器是它后边的函数的运行时的声明。函数装饰器是写成一行,就在定义函数或方法的def语句之前,而且由@符号、后面跟着所谓的元函数(metafunction)组成:也就是管理另一函数(或其他可调用对象)的函数。

如今的静态方法可以用下面的装饰器语法编写。

从内部来看,这个语法和下面的写法有相同效果(把函数传递给装饰器,再赋值给最初的变量名)。

类装饰器类似于函数装饰器,但是,它们在一条class语句的末尾运行,并且把一个类名重新绑定到一个可调用对象。

被映射为下列相当代码:

元类是一种类似的基于类的高级工具,其用途往往与类装饰器有所重合。它们提供了一种可选的模式,会把一个类对象的创建导向到顶级type类的一个子类,在一条class语句的最后:

在Python2.6中,在类头部使用一个类属性而不是一个关键字参数:

元类通常重新定义type类的newinit方法,以实现对一个新的类对象的创建和初始化的控制。

  1. 修改类属性的副作用: 会影响子类和实例对象。
  2. 修改可变的类属性也可能产生副作用:譬如通过实例修改类的一个list列表内容,其他所有共享这个列表的内容也都变了。
  3. 多重继承:顺序很重要。 搜索先左后右,广度优先。
  4. ”过度包装“:如果类层次太深,程序就会变得晦涩难懂。

  • try/finally 无论异常是否发生,执行清理行为。
  • raise 手动在代码中触发异常。
  • assert 有条件地在程序代码中触发异常。

第33章 异常编码细节

else: #没有异常时,执行

利用这个变体,Python可先执行try首行下的语句代码块。接下来发生的事情,取决于try代码块中是否发生异常。

  • 如果try代码块运行时没有异常发生,Python会跳至执行finally代码块,然后在整个try语句后继续执行下去。
  • 如果try代码块运行时有异常发生,python依然会回来运行finally代码块,但是接着会把异常向上传递到较高的try语句或顶层默认处理器。程序不会在try语句下继续执行。

现在完整的try版本:

要显式地触发异常,可以使用raise语句: raise关键字,后面跟着可选的要引发的类或者类的一个实例。

raise <class> #自动调用不带构造参数的类,以创建被引发的一个实例。 raise #把最近的异常重新触发下。

当使用from的时候,第二个表达式指定了另一个异常类或实例,它会附加到引发异常的__cause__属性。

执行起来就像如下的代码。

assert语句是附加的功能,如果使用-O Python命令行标志位,就会从程序编译后的字节码中移除,从而优化程序。

assert几乎就是用来收集用户定义的约束条件,而不是捕捉内在的程序设计错误。

with/as语句的设计是作为常见try/finally用法模式的替代方案。就像try/finally语句,with/as语句也是用于定义必须执行的终止或”清理”行为,无论处理步骤中是否发生异常。
不过,和try/finally不同的是,with语句支持更丰富的基于对象的协议,可以为代码块定义支持进入和离开动作。

with语句的基本格式如下。

在这里的expression要返回一个对象,从而支持环境管理协议。

以下是with语句实际的工作方式。

  1. 计算表达式,所得到的对象称为环境管理器,它必须有__enter____exit__方法。
  2. 环境管理器的__enter__方法会被调用。如果as子句存在,其返回值会赋值给as子句中的变量,否则,直接丢弃。
  3. 代码块中的嵌套的代码会执行。
  4. 如果with代码块引发异常,__exit__(type,value,traceback)方法就会被调用(带有异常细节)。这引起也是由sys.exc_info返回的相同值。如果此方法返回值为假,则异常会重新引发。否则,异常会终止。正常情况下异常是应该被重新引发,这样的话才能传递到with语句之外。

以下是实际在Python3.0中运行的脚本:

基于类的异常有如下特点。

  • 提供类型分类,对今后的修改有更好的支持。

在Python2.6和Python3.0之前,可以使用类实例和字符串对象来定义异常。

字符串异常和类异常的主要差别在于,引发的异常在try语句中的excepte子句匹配时的方式不同。

  • 字符串异常是以简单对象识别来匹配的:引发的异常是由Python的is测试来匹配except子句的。
  • 类异常是由超类关系进行匹配的:只要excepte子句列举了异常的类或其任何超类名,引发的异常就会匹配该子句。

当发生异常时,Python会回到最近进入、具有相符except分句的try语句。因为每个try语句都会留下标识,Python可检查堆栈的标识,从而跳回到较早的try。
这种处理器的嵌套化,就是我们所谈到的异常向上传递至较高的处理器的意思:这类处理器就是在程序执行流程中较早进入的try语句。

  1. 异常不总是错误。譬如EOFERROR用来标识文件结束。
  2. 函数信号条件和raise。有些时候,我们不能用返回值来代表不寻常的情况,这种时候用异常反而比较好。它代表了某种信号,而不是真的发生异常了。
  3. 关闭文件和服务器连接。
  4. 在try外进行调试。可以利用异常处理器,取代Python的默认顶层异常处理行为(一般用于开发期间调式)。

sys.exc_info允许一个异常处理器获取对最近引发的异常的访问。如果没有处理器正在处理,就返回包含了三个None值的元组。否则,将会返回(type、value和traceback):

  • type是正在处理的异常的异常类型。
  • value是引发的异常类实例。
  • traceback是一个traceback对象,代表异常最初发生时所调用的堆栈。

* 经常会失败的运算一般都应该包装在try语句内。如文件开启、套接字调用等。
* 应该在try/finally中实现终止动作,从而保证它们的执行,除非环境管理器作为一个with/as选项可用。
* 偶尔,把对大型函数的调用包装在单个try语句内。

捕捉太多:避免空except语句
Python可选择要捕捉哪些异常,有时候必须小心,不要涵盖太广。
try带空except时,可能会不知不觉阻止重要的结束,如下面文件所示:

经验法则是,尽量让处理器具体化:空except子句很方便,但是可能容易出错。

捕捉过少:使用基于类的分类

高级的字符串表示法在Python当前版本中已经产生了分歧:

  • Python3.0为二进制数据提供了一种替代字符器类型,并且在其常规的字符串类型中支持Unicode文本(ASCII看作是Unicode的一种简单类型)
  • Python2.6为非ASCII Unicode文本提供了一种替代字符串类型,并且在其常规的字符串类型中支持简单文本和二进制数据。

同样的一个字符串可以有多少编码方式,譬如’a’可以按ASCII编码也可以按unicode编码。
字节和字符串之间的来回转换由两个术语定义:

  • 编码是根据一个想要的编码名称,把一个字符串翻译为其原始字节形式。
  • 解码是根据其编码名称,把一个原始字节串翻译为字符串形式的过程。

Python2.X有一种通用的字符串类型来表示二进制数据和像ASCII这样的8位文本,还有一种特定的类型用来表示多字节Unicode文本:

  • str表示8位文本和二进制数据。

Python3.X带有3种字符串对象类型– 一种用于文本数据,两种用于二进制数据:

  • bytes表示二进制数据。

Python3.0的str类型定义为一个不可改变的字符序列
Python3.0中,bytes类型定义为一个8位整数的不可变序列,表示绝对的字节值。为了方便起见,bytes对象打印为字符串而不是整数。

Python现在在文本文件和二进制文件之间做了一个明显的独立于平台的区分:

  1. 文本文件。当一个文件以文本模式打开的时候,读取其数据会自动将其内容解码,并且将其内容返回为一个str,写入会接受一个str,并且在将其传输到文件之间自动编码。
  2. 二进制文件。通过在内置的open调用的模式字符串参数添加一个b(只能小写),以二进制模式打开一个文件的时候,读取其数据不会以任何方式解码它,而是直接返回其内容raw并且未经修改,写也一样不会修改。

在Python3.0中,所有当前字符串常量形式,’xxx’、”xxx”和三引号字符串块,都产生一个str;在它们任何一种前面添加一个b或B,则会创建一个bytes。

Python3.0基本上要求遵守一种类型或另一种类型,或者手动执行显式转换:

十六进制转义限制于单个字节的值;”uNNNN”用来编码1个2字节字符码;”UNNNNNNNN”编码4字节宽度的字符。

首先,Python3.0允许特殊的字符以十六进制和Unicode转义的方式编码到str字符串中,但是,只能以十六进制转义的方式编码到bytes字符串中:Unicode转义会默默地逐字转换为字节常量,而不是转义。
其次,字节常量要求字符要么是ASCII字符,要么如果它们的值大于127就进行转义。
另一方面,str字符串允许常量包含源字符集中的任何字符:

尽管Python3.0中所有的三种字符串类型都可以包含字符值并且支持很多相同的操作,但我们总是应该:

  • 对文本数据使用str;
  • 对二进制数据使用bytes;
  • 对想要原处修改的二进制数据使用bytearray。

用哪种模式打开一个文件,它决定了在脚本中将要使用哪种对象类型表示文件的内容。文本模式意味着str对象,二进制模式意味着bytes对象:

  • 文本模式文件根据Unicode编码来解释文件内容,要么是平台的默认编码,要么是我们传递进的编码名。通过传递一个编码名来打开文件,我们可以强行进行Unicode文件的各种类型的转换。文本模型的文件也执行通用的行末转换:默认地,所有的行末形式(包括’r’,’n’,’rn’)映射为脚本中的一个单个的’n’字符,而不管在什么平台上运行。正如前面所描述的,文本文件也负责阅读和写入在某些Unicode编码方案中存储文件开始处的字节顺序标记(Byte
  • 二进制模式文件不会返回原始的文件内容,而是作为表示字节值的整数的一个序列,没有编码或解码,也没有行末转换。

在Windows下文本文件自动把n行末字符和rn相互映射,而二进制文件不这么做。

一些编码方式在文件的开始处存储了一个特殊的字节顺序标记(BOM)序列,来指定数据的大小尾方式或编码类型。如果编码名暗示了BOM的时候,Python在输入和将其输出的时候都会忽略该标记,但是有时候必须使用一个特定的编码名称来迫使显式地处理BOM。

Python3.0中其他字符串工具的变化

  1. re模式匹配模块。这个模块已经泛化为可以用于Python3.0中的任何字符串类型的对象–str、bytes和bytearray,并且返回同样类型的结果子字符串作为目标字符串。
  2. Struct二进制数据模块。打包的数据只是作为bytes和bytearray对象显示,而不是str对象。
    附加两个struct格式说明表格:
  1. Pickle对象序列化模块。pickle模块的Python3.0版本总是创建一个bytes对象。所以写入文件时,需要以二进制模式打开。
  2. XML解析工具。SAX和DOM解析模式。

插入在属性访问时运行的代码

  1. __getattr__和__setattr__方法,把未定义的属性获取和所有的属性赋值指向通用的处理器方法。
  2. property内置函数,把特定属性访问定位到get和set处理器函数,也叫做特性(Property)。
  3. 描述符协议,把特定属性访问定位到具有任意get和set处理方法的类的实例。

特性协议允许我们把一个特定属性的get和set操作指向我们所提供的函数或方法,使得我们能够插入在属性访问的时候自动运行的代码,拦截属性删除,并且如果愿意的话,还可为属性提供文档。

四个参数如果没有传的话,默认为None,意味着相应的操作不支持,如果调用了就会引发一个异常。

利用装饰器语法可以简化特定的写法。如下示例:

对于Python2.6,property对象也有getter、setter和deleter方法,这些方法指定相应的特性访问器方法赋值并且返回特性自身的一个副本。

描述符也管理一个单个的、特定的属性。特性实际中只是创建一种特写描述符的方便方法。
描述符作为单独的类编写,并且针对想要拦截的属性访问操作提供特定命名的访问器方法–当以相应的方式访问分配给描述符类实例的属性时,描述符类中的获取、设置和删除等方法自动运行:

带有任何这些方法的类都可以看作是描述符,并且当它们的一个实例分配给另一个类的属性的时候,它们的这些方法是特殊的–当访问属性的时候,会自动调用它们。
和特性不同,省略一个__set__意味着允许这个名字在一个实例中重新定义,因此,隐藏了描述符–要使得一个属性是只读的,我们必须定义__set__来捕获赋值并引发一个异常。

当获取X.attr的时候,就好像发生了如下的转换:

当描述符的实例参数为None的时候,该描述符知道将直接访问它。

描述符可以使用实例状态和描述符状态,或者二者的任何组合:

  • 描述符状态用来管理内部用于描述符工作的数据。
  • 实例状态记录了和客户类相关的信息,以及可能由客户类创建的信息。

特性和描述符是如何相关的
可以用下面的描述符来模拟property内置函数。

  • __getattr__针对未定义的属性运行–也就是说,属性没有存储在实例上,或者没有从其类之一继承。
  • __getattribute__针对每个属性,因此,当使用它的时候,必须小心避免通过把属性访问传递给超类而导致递归循环。

避免属性拦截方法中的循环

2.利用超类方法调用。

对于隐式地使用内置操作获取的方法名属性,这些方法(__getattr____getattribute__等)可能根本不会运行。这意味着操作符重载方法调用不能委托给被包装的对象,除非包装类自己重新定义这些方法。

如针对__str____add____getitem__方法的属性获取分别通过打印、+表达式和索引隐式运行,而不会指向Python3.0中的类属性拦截方法。特别是:

  • 在Python2.6中,如果属性在类中未定义的话,__getattr__会针对这样的属性运行。

在Python2.X中,这样的操作调用的方法在运行时从实例中查找,就像所有其他属性一样;在Python3.0中,这样的方法在中查找。

装饰是为函数和类指定管理代码的一种方式。装饰器本身的形式是处理其他的可调用对象的可调用对象(如函数)。
装饰器提供了一种方法,在函数和类定义语句的末尾插入自动运行代码

通过针对随后的调用安装包装器对象可以实现:

  • 函数装饰器安装包装器对象,以在需要的时候拦截随后的函数调用并处理它们。
  • 类装饰器安装包装器对象,以在需要的时候拦截随后的实例创建调用并处理它们。

这本书里有好多装饰器的使用,可以参考下。

  1. 装饰器有一种非常明确的语法,这使得它们比那些可能任意地远离主体函数或类的辅助函数调用更容易为人们发现。
  2. 当主体函数或类定义的时候,装饰器应用一次;在对类或函数的每次调用的时候,不必添加额外的代码。
  3. 由于前面两点,装饰器使得一个API的用户不太可能忘记根据API需要扩展一个函数或类。

函数装饰器是一种关于函数的运行时声明,函数的定义需要遵守此声明。
装饰器在紧挨着定义一个函数或方法的def语句之前的一行编写,并且它由@符号以及紧随其后的对于元函数的一个引用组成–这是管理另一个函数的一个函数。

在编码方面,函数装饰器自动将如下的语法:

映射为这一对等的形式,其中装饰器是一个单参数的可调用对象,它返回与F具有相同数目的参数的一个可调用对象:

这一自动名称重绑定在def语句上有效,不管它针对一个简单的函数或是类中的一个方法。当随后调用F函数的时候,它自动调用装饰器所返回的对象,该对象可能是实现了所需的包装逻辑的另一个对象,或者是最初的函数本身。

装饰器自身是一个返回可调用对象的可调用对象
有一种常用的编码模式–装饰器返回了一个包装器,包装器把最初的函数保持到一个封闭的作用域中:

当随后调用名称func的时候,它硬实调用装饰器所返回的包装器函数;随后包装器函数可能会运行最初的func,因为它在一个封闭的作用域中仍然可以使用。当以这种方式编码的时候,每个装饰器的函数都会产生一个新的作用域来保持状态。

我们也可以通过对类来重载call方法,从而把类转成一个可调用对象,并且使用实例属性而不是封闭的作用域:

有一点需要注意,通过类实现的装饰器对象并不能工作在类方法上。
因为:当一个方法名绑定只是绑定到一个简单的函数时,Python向self传递了隐含的主体实例;当它是一个可调用类的实例的时候,就传递这个类的实例。
从技术上讲,当方法是一个简单函数的时候,Python只是创建了一个绑定的方法对象,其中包含了主体实例。
反而是利用封闭作用域的嵌套函数工作的更好,既能支持简单函数,也能支持实例方法。

类装饰器和函数装饰器很类似,只不过管理的是类。
通过函数实现,返回了一个包装器类。

每个被装饰的类都创建一个新的作用域,它记住了最初的类。

工厂函数通常在封闭的作用域引用中保持状态,类通常在属性中保持状态。

需要注意通过类实现的类装饰器,看如下的错误示例:

每个被装饰的类都返回了一个Decorator的实例。
但是对给定的类创建多个实例时出问题了—会对一个Decorator实例反复调用call方法,从而后面的的实例创建调用都覆盖了前面保存的实例。。(也许我们可以利用这个特性来实现单例模式??)

为了支持多步骤的扩展,装饰器语法允许我们向一个装饰的函数或方法添加包装器逻辑的多个层。
这种形式的装饰器语法:

函数装饰器和类装饰器似乎都能接受参数,尽管实际上这些参数传递给了真正返回装饰器的一个可调用对象,而装饰器反过来又返回了一个可调用对象。例如,如下代码:

自动地映射到其对等的形式,其中装饰器是一个可调用对象,它返回实际的装饰器。返回的装饰器反过来返回可调用的对象,这个对象随后运行以调用最初的函数名:

装饰器参数在装饰发生之前就解析了,并且它们通常用来保持状态信息供随后的调用使用。
例如,这个例子中的装饰器函数,可能采用如下的形式:

换句话说,装饰器参数往往意味着可调用对象的3个层级:接受装饰器参数的一个可调用对象,它返回一个可调用对象以作装饰器,该装饰器返回一个可调用对象来处理对最初的函数或类的调用。这3个层级的每一个都可能是一个函数或类,并且可能以作用域或类属性的形式保存了状态。

装饰器不光可以管理随后对函数和类的调用,还能管理函数和类本身。如下所示,返回函数和类本身:

函数装饰器有几种办法来保持装饰的时候所提供的状态信息,以便在实际函数调用过程中使用:

在运用描述符的情况下,我们也能把通过类实现的装饰器运用到 类方法上,只是有点复杂,如下所示:

这个例子中把wrapper类改成嵌套的函数也可以,而且代码量更少,如下:

类装饰器(函数装饰器)的两个潜在缺陷:

  • 类型修改。当插入包装器的时候,一个装饰器函数或类不会保持其最初的类型–其名称重新绑定到一个包装器对象,在使用对象名称或测试对象类型的程序中,这可能会很重要。
  • 额外调用。通过装饰添加一个包装层,在每次调用装饰对象的时候,会引发一次额外调用所需要的额外性能成本–调用是相对耗费时间的操作。

与管理器(即辅助)函数解决方案相比,装饰器提供:

  • 在调用中,所有的位置参数出现在所有关键字参数之前。
  • 在def中,所有的非默认参数出现在所有的默认参数之前。

装饰器参数 VS 函数注解
利用函数注解,可以简化功能的实现:因为状态信息现在在函数自身,装饰器不再需要一层封闭的作用域来保持状态。
对比下装饰器参数代码和函数注解的代码:

从某种意义上讲,元类只是扩展了装饰器的代码插入模式。
元类主要是针对那些构建API和工具供他人使用的程序员。

  1. 类特性。内置函数property。拦截特定的属性。
  2. 类属性描述符。拦截特定的属性。特定只是定义根据访问自动运行函数的属性描述符的一种简洁方式。

元类允许我们在在一条class语句的末尾,插入当创建一个类对象的时候自动运行的逻辑。
这个逻辑不会把类名重新绑定到一个装饰器可调用对象,而是把类自身的创建指向特定的逻辑。

和类装饰器不同,它通常是添加实例创建时运行的逻辑,元类在类创建时运行。
同样的,它们都是通常用来管理或扩展类的钩子,而不是管理其实例。

通过声明一个元类,我们告诉Python把类对象的创建路由到我们所提供的另一个类:

由于创建类的时候,Python在class语句的末尾自动调用元类,因此它可以根据需要扩展、注册或管理类。

  • 在Python3.0中,用户定义的类对象是名为type的对象的实例,type本身是一个类。
  • 在Python2.6中,新式类继承自object,它是type的一个子类;传统类是type的一个实例,并且并不创建自一个类。
    实例创建自类,而类创建自type。
  • 类型由派生自type的类定义。
  • 用户定义的类是类型类的实例。
  • 用户定义的类是产生它们自己的实例的类型。

类根本不是一个独立的概念:它们就是用户定义的类型,并且type自身也是由一个类定义的。

由于类实际上是type类的实例,从type的定制的子类创建类允许我们实现各种定制的类。

  • type是产生用户定义的类的一个类。
  • 元类是type类的一个子类。
  • 类对象是type类的一个实例,或一个子类。
  • 实例对象产生自一个类。

换句话说,为了控制创建类以及扩展其行为的方式,我们所需要做的只是指定个用户定义的类创建自一个用户定义的元类,而不是常规的type类。

从技术上讲,Python遵从一个标准的协议来使这发生:在一条class语句的末尾,并且在运行了一个命名控件词典中的所有嵌套代码之后,它调用type对象来创建class对象:

type对象反过来定义了一个__call__运算符重载方法,当调用type对象的时候,该方法运行两个其他方法:

__new__方法创建并返回了新的class对象,并且随后__init__方法初始化了新创建的对象。
这是type的元类子类通常用来定制类的钩子。

尽管重新定义type超类的__new____init__方法是元类向类对象创建过程插入逻辑的最常见方法,其他方案也是可能的。
实际上任何可调用对象都可以用作一个元类,只要它接收传递的参数并且返回与目标类兼容的一个对象。

另外,我们也可以重定义元类的__call__, 以拦截创建调用。

  • 元类继承自type类。
  • 元类声明由子类继承。在用户定义的类中,metaclass=M声明由该类的子类继承,因此,对于在超类链中继承了这一声明的每个类的构建,该元类都将运行。
  • 元类属性没有由类实例继承。元类声明指定了一个实例关系,它和继承不同。由于类是元类的实例,所以元类中定义的行为应用于类,而不是类随后的实例。实例从它们的类和超类获取行为,但是,不是从任何元类获取行为。从技术上讲,实例属性查找通过只是搜索实例及期所有类的__dict__字典;元类不包含在实例查找中。

元类与类装饰器在功能上有重合。

  • 在class语句末尾,类装饰器把类名重新绑定到一个函数的结果。
  • 元类通过在一条class语句的末尾把类对象创建过程路由到一个对象来工作。
}

我要回帖

更多关于 英语语法基础知识大全 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信