• 关于 Raise 方法 的搜索结果

回答

取决于引发哪个异常。 方法引发异常: def some(self): try: msg = "My Exception" raise HTTPNotFound(msg) except Exception as e: raise e 方法捕获异常 try: some() except HTTPNotFound as e: print "Not found exception" except Exception as e: print "Generic Exception"

祖安文状元 2020-02-22 18:01:37 0 浏览量 回答数 0

问题

Python简单使用插件结构,python报错

python小菜菜 2020-05-27 14:48:21 3 浏览量 回答数 1

问题

Python简单使用插件结构:报错 

kun坤 2020-06-04 21:16:30 3 浏览量 回答数 1

智能视觉生产免费体验

图像视频分割、图像编辑、图像分析,互娱、电商行业必备

问题

Python简单使用插件结构 - python报错

montos 2020-06-04 14:01:19 3 浏览量 回答数 1

回答

自定义某个属性的一种简单方法是将它定义为一个property。 例如,下面的代码定义了一个property,增加对一个属性简单的类型检查: class Person: def __init__(self, first_name): self.first_name = first_name # Getter function @property def first_name(self): return self._first_name # Setter function @first_name.setter def first_name(self, value): if not isinstance(value, str): raise TypeError('Expected a string') self._first_name = value # Deleter function (optional) @first_name.deleter def first_name(self): raise AttributeError("Can't delete attribute") 上述代码中有三个相关联的方法,这三个方法的名字都必须一样。 第一个方法是一个 getter 函数,它使得 first_name 成为一个属性。 其他两个方法给 first_name 属性添加了 setter 和 deleter 函数。 需要强调的是只有在 first_name 属性被创建后, 后面的两个装饰器 @first_name.setter 和 @first_name.deleter 才能被定义。 property的一个关键特征是它看上去跟普通的attribute没什么两样, 但是访问它的时候会自动触发 getter 、setter 和 deleter 方法。例如: >>> a = Person('Guido') >>> a.first_name # Calls the getter 'Guido' >>> a.first_name = 42 # Calls the setter Traceback (most recent call last): File "<stdin>", line 1, in <module> File "prop.py", line 14, in first_name raise TypeError('Expected a string') TypeError: Expected a string >>> del a.first_name Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: can`t delete attribute >>> 在实现一个property的时候,底层数据(如果有的话)仍然需要存储在某个地方。 因此,在get和set方法中,你会看到对 _first_name 属性的操作,这也是实际数据保存的地方。 另外,你可能还会问为什么 __init__() 方法中设置了 self.first_name 而不是 self._first_name 。 在这个例子中,我们创建一个property的目的就是在设置attribute的时候进行检查。 因此,你可能想在初始化的时候也进行这种类型检查。通过设置 self.first_name ,自动调用 setter 方法, 这个方法里面会进行参数的检查,否则就是直接访问 self._first_name 了。 还能在已存在的get和set方法基础上定义property。例如: class Person: def __init__(self, first_name): self.set_first_name(first_name) # Getter function def get_first_name(self): return self._first_name # Setter function def set_first_name(self, value): if not isinstance(value, str): raise TypeError('Expected a string') self._first_name = value # Deleter function (optional) def del_first_name(self): raise AttributeError("Can't delete attribute") # Make a property from existing get/set methods name = property(get_first_name, set_first_name, del_first_name)

哦哦喔 2020-04-17 15:02:17 0 浏览量 回答数 0

回答

通过raise DropItem()方法

珍宝珠 2019-12-02 03:20:39 0 浏览量 回答数 0

回答

我们可以使用三种方法来处理多个异常。 第一种方法需要把所有可能发生的异常放到一个元组里。像这样: try: file = open('test.txt', 'rb') except (IOError, EOFError) as e: print("An error occurred. {}".format(e.args[-1])) 另外一种方式是对每个单独的异常在单独的except语句块中处理。我们想要多少个except语句块都可以。这里是个例子: try: file = open('test.txt', 'rb') except EOFError as e: print("An EOF error occurred.") raise e except IOError as e: print("An error occurred.") raise e 上面这个方式中,如果异常没有被第一个except语句块处理,那么它也许被下一个语句块处理,或者根本不会被处理。 现在,最后一种方式会捕获所有异常: try: file = open('test.txt', 'rb') except Exception: # 打印一些异常日志,如果你想要的话 raise 当你不知道你的程序会抛出什么样的异常时,上面的方式可能非常有帮助。

montos 2020-04-16 20:44:09 0 浏览量 回答数 0

回答

内置函数next不使用None作为默认值。实际上,正如您在C源代码(对于cpython,官方Python解释器)中所看到的那样,其参数处理非常低级。纯Python等效项将在函数定义中使用* rgs并手动检查是否有一个或两个参数。可能是这样的: def next(\*rgs): assert(1 <= len(args) <= 2) try: return args[0].__next__() except StopIteration: if len(args) > 1: return args[1] else: raise 在Python中复制类似行为的一种更好的方法是使用默认值,该默认值对于外部代码意外提供是不可能的。这是执行此操作的一种好方法: _sentinel = object() # a unique object that no user should ever pass to us def next(iterator, default=_sentinel): try: return iterator.__next__() except StopIteration: if default is not _sentinel: return default else: raise 回答来源:stackoverflow

is大龙 2020-03-24 00:06:01 0 浏览量 回答数 0

回答

考虑下一个简单的类,它的属性由属性方法包装: class Person: def __init__(self, name ,age): self.name = name self.age = age @property def name(self): return self._name @name.setter def name(self, value): if not isinstance(value, str): raise TypeError('name must be a string') self._name = value @property def age(self): return self._age @age.setter def age(self, value): if not isinstance(value, int): raise TypeError('age must be an int') self._age = value 可以看到,为了实现属性值的类型检查我们写了很多的重复代码。 只要你以后看到类似这样的代码,你都应该想办法去简化它。 一个可行的方法是创建一个函数用来定义属性并返回它。例如: def typed_property(name, expected_type): storage_name = '_' + name @property def prop(self): return getattr(self, storage_name) @prop.setter def prop(self, value): if not isinstance(value, expected_type): raise TypeError('{} must be a {}'.format(name, expected_type)) setattr(self, storage_name, value) return prop # Example use class Person: name = typed_property('name', str) age = typed_property('age', int) def __init__(self, name, age): self.name = name self.age = age

哦哦喔 2020-04-17 16:26:40 0 浏览量 回答数 0

问题

在C#中从SQL捕获异常的最佳实践

保持可爱mmm 2019-12-01 22:00:07 11 浏览量 回答数 1

回答

方法一:现在用 notepad++,在 UTF-8 格式下编写以下语句:coding=utf-8print"打印中文字符"方法二:用encode和decode如:?1234567891011import os.pathimport xlrd,sysFilename='/home/tom/Desktop/1234.xls'if not os.path.isfile(Filename): raise NameError,"%s is not a valid filename"%Filenamebk=xlrd.open_workbook(Filename)shxrange=range(bk.nsheets)print shxrangefor x in shxrange: p=bk.sheets()[x].name.encode('utf-8') print p.decode('utf-8')方法三:在文件开头加上:?12reload(sys)sys.setdefaultencoding('utf8')这2行,再试着运行一下希望本文所述对大家的Python程序设计有所帮助。

xuning715 2019-12-02 01:10:45 0 浏览量 回答数 0

回答

方法一:用encode和decode如:?1234567891011import os.pathimport xlrd,sysFilename='/home/tom/Desktop/1234.xls'if not os.path.isfile(Filename): raise NameError,"%s is not a valid filename"%Filenamebk=xlrd.open_workbook(Filename)shxrange=range(bk.nsheets)print shxrangefor x in shxrange: p=bk.sheets()[x].name.encode('utf-8') print p.decode('utf-8')方法二:在文件开头加上:?12reload(sys)sys.setdefaultencoding('utf8')这2行,再试着运行一下希望本文所述对大家的Python程序设计有所帮助。

xuning715 2019-12-02 01:10:17 0 浏览量 回答数 0

回答

`def _check_collection(method):''' Decorate mehtod to validate collection arguments ''' @functools.wraps(method) def wrapped(self, collection, **kwargs): if collection not in self.COLLECTIONS: # logger.error('%s not in permit collections tuple', table) raise HTTPError(500, 'Internal server error') return method(self, collection, **kwargs) return wrapped`装饰器忘记调用 db 操作方法了。

落地花开啦 2019-12-02 01:49:06 0 浏览量 回答数 0

回答

考虑如下的代码,它定义了一个property: class Person: def __init__(self, name): self.name = name # Getter function @property def name(self): return self._name # Setter function @name.setter def name(self, value): if not isinstance(value, str): raise TypeError('Expected a string') self._name = value # Deleter function @name.deleter def name(self): raise AttributeError("Can't delete attribute") 下面是一个示例类,它继承自Person并扩展了 name 属性的功能: class SubPerson(Person): @property def name(self): print('Getting name') return super().name @name.setter def name(self, value): print('Setting name to', value) super(SubPerson, SubPerson).name.__set__(self, value) @name.deleter def name(self): print('Deleting name') super(SubPerson, SubPerson).name.__delete__(self) 接下来使用这个新类: >>> s = SubPerson('Guido') Setting name to Guido >>> s.name Getting name 'Guido' >>> s.name = 'Larry' Setting name to Larry >>> s.name = 42 Traceback (most recent call last): File "<stdin>", line 1, in <module> File "example.py", line 16, in name raise TypeError('Expected a string') TypeError: Expected a string >>> 如果你仅仅只想扩展property的某一个方法,那么可以像下面这样写: class SubPerson(Person): @Person.name.getter def name(self): print('Getting name') return super().name 或者,你只想修改setter方法,就这么写: class SubPerson(Person): @Person.name.setter def name(self, value): print('Setting name to', value) super(SubPerson, SubPerson).name.__set__(self, value

哦哦喔 2020-04-17 15:03:11 0 浏览量 回答数 0

回答

可以直接作用于for循环的对象统称为可迭代对象(Iterable)。 可以被next()函数调用并不断返回下一个值的对象称为迭代器(Iterator)。 所有的Iterable均可以通过内置函数iter()来转变为Iterator。 对迭代器来讲,有一个__next()就够了。在你使用for 和 in 语句时,程序就会自动调用即将被处理的对象的迭代器对象,然后使用它的next__()方法,直到监测到一个StopIteration异常。 Python L = [1,2,3][x**2 for x in L][1, 4, 9]next(L) Traceback (most recent call last): File "", line 1, in TypeError: 'list' object is not an iterator I=iter(L)next(I) 1 next(I) 2 next(I) 3 next(I) Traceback (most recent call last): File "", line 1, in StopIteration123456789101112131415161718 L = [1,2,3][x**2 for x in L] [1, 4, 9] next(L) Traceback (most recent call last): File "", line 1, in TypeError: 'list' object is not an iterator I=iter(L)next(I) 1 next(I) 2 next(I) 3 next(I) Traceback (most recent call last): File "", line 1, in StopIteration上面例子中,列表L可以被for进行循环但是不能被内置函数next()用来查找下一个值,所以L是Iterable。 L通过iter进行包装后设为I,I可以被next()用来查找下一个值,所以I是Iterator。 题外话: 内置函数iter()仅仅是调用了对象的__iter()方法,所以list对象内部一定存在方法iter__()内置函数next()仅仅是调用了对象的__next()方法,所以list对象内部一定不存在方法next__(),但是Itrator中一定存在这个方法。for循环内部事实上就是先调用iter()把Iterable变成Iterator在进行循环迭代的。Python L = [4,5,6]I = L.__iter__()L.__next__() Traceback (most recent call last): File "", line 1, in AttributeError: 'list' object has no attribute '__next__' I.__next__() 4 from collections import Iterator, Iterableisinstance(L, Iterable) True isinstance(L, Iterator) False isinstance(I, Iterable) True isinstance(I, Iterator) True [x**2 for x in I] [25, 36]12345678910111213141516171819 L = [4,5,6]I = L.__iter__()L.__next__() Traceback (most recent call last): File "", line 1, in AttributeError: 'list' object has no attribute '__next__' I.__next__() 4 from collections import Iterator, Iterableisinstance(L, Iterable) True isinstance(L, Iterator) False isinstance(I, Iterable) True isinstance(I, Iterator) True [x**2 for x in I] [25, 36]4.Iterator继承自Iterable,从下面的测试中可以很方便的看到Iterator包含__iter()和next()方法,而Iteratble仅仅包含iter__()。 Python from collections import Iterator, Iterablehelp(Iterator) Help on class Iterator: class Iterator(Iterable) | Method resolution order: | Iterator | Iterable | builtins.object |**注解:从这里可以看出Iterable继承自object, Iterator继承自Iterable。 | Methods defined here: | | __iter__(self) | | __next__(self) | Return the next item from the iterator. When exhausted, raise StopIteration...... help(Iterable) Help on class Iterable: class Iterable(builtins.object) | Methods defined here: | | __iter__(self)......12345678910111213141516171819202122232425 from collections import Iterator, Iterablehelp(Iterator) Help on class Iterator: class Iterator(Iterable) | Method resolution order: | Iterator | Iterable | builtins.object |**注解:从这里可以看出Iterable继承自object, Iterator继承自Iterable。 | Methods defined here: | | __iter__(self) | | __next__(self) | Return the next item from the iterator. When exhausted, raise StopIteration...... help(Iterable) Help on class Iterable: class Iterable(builtins.object) | Methods defined here: | | __iter__(self)...... iterable需要包含有__iter()方法用来返回iterator,而iterator需要包含有next__()方法用来被循环 如果我们自己定义迭代器,只要在类里面定义一个 iter() 函数,用它来返回一个带 next() 方法的对象就够了。 直接上代码 Python class Iterable: def __iter__(self): return Iterator() class Iterator: def __init__(self): self.start=-1 def __next__(self): self.start +=2 if self.start >10: raise StopIteration return self.start I = Iterable()for i in I: print(i) 12345678910111213141516class Iterable: def __iter__(self): return Iterator() class Iterator: def __init__(self): self.start=-1 def __next__(self): self.start +=2 if self.start >10: raise StopIteration return self.start I = Iterable()for i in I: print(i) 上面的代码实现的是找到10以内的奇数,代码中的类名可以随便取,不是一定需要使用我上面提供的类名的。 如果在Iterator的__next__方法中没有实现StopIteration异常,那么则是表示的全部奇数,那么需要在调用的时候设置退出循环的条件。 Python class Iterable: def __iter__(self): return Iterator() class Iterator: def __init__(self): self.start=-1 def __next__(self): self.start +=2 return self.start I = Iterable()for count, i in zip(range(5),I): #也可以用内置函数enumerate来实现计数工作。 print(i) 1234567891011121314class Iterable: def __iter__(self): return Iterator() class Iterator: def __init__(self): self.start=-1 def __next__(self): self.start +=2 return self.start I = Iterable()for count, i in zip(range(5),I): #也可以用内置函数enumerate来实现计数工作。 print(i) 我们通过range来实现打印多少个元素,这里表示打印5个元素,返回结果和上面一致。 当然,我们可以把这两个类合并在一起,这样实现程序的简练。最终版本如下 Python class Iterable: def __iter__(self): return self def __init__(self): self.start=-1 def __next__(self): self.start +=2 if self.start >10: raise StopIteration return self.start I = Iterable()for i in I: print(i) 1234567891011121314class Iterable: def __iter__(self): return self def __init__(self): self.start=-1 def __next__(self): self.start +=2 if self.start >10: raise StopIteration return self.start I = Iterable()for i in I: print(i) 复制迭代器 迭代器是一次性消耗品,使用完了以后就空了,请看。 Python L=[1,2,3]I=iter(L)for i in I: ... print(i, end='-')...1-2-3- next(I) Traceback (most recent call last): File "", line 1, in StopIteration12345678910 L=[1,2,3]I=iter(L)for i in I: ... print(i, end='-')...1-2-3- next(I) Traceback (most recent call last): File "", line 1, in StopIteration当循环以后就殆尽了,再次使用调用时会引发StopIteration异常。 我们想通过直接赋值的形式把迭代器保存起来,可以下次使用。但是通过下面的范例可以看出来,根本不管用。 Python I=iter(L)J=Inext(I) 1 next(J) 2 next(I) 3 next(J) Traceback (most recent call last): File "", line 1, in StopIteration123456789101112 I=iter(L)J=Inext(I) 1 next(J) 2 next(I) 3 next(J) Traceback (most recent call last): File "", line 1, in StopIteration那怎么样才能达到我们要的效果呢? 我们需要使用copy包中的deepcopy了,请看下面: Python import copyI=iter(L)J=copy.deepcopy(I)next(I) 1 next(I) 2 next(J) 1123456789 import copyI=iter(L)J=copy.deepcopy(I)next(I) 1 next(I) 2 next(J) 1补充:迭代器不能向后移动, 不能回到开始。 所以需要做一些特殊的事情才能实现向后移动等功能。 以上代码均在Python 3.4 中测试通过。 日志: 8月13日完成8月14日添加关于Iterator, Iterable的更多解释在题外话的第4点。

xuning715 2019-12-02 01:10:08 0 浏览量 回答数 0

回答

在程序中引入自定义异常可以使得你的代码更具可读性,能清晰显示谁应该阅读这个代码。 还有一种设计是将自定义异常通过继承组合起来。在复杂应用程序中, 使用基类来分组各种异常类也是很有用的。它可以让用户捕获一个范围很窄的特定异常,比如下面这样的: try: s.send(msg) except ProtocolError: ... 你还能捕获更大范围的异常,就像下面这样: try: s.send(msg) except NetworkError: ... 如果你想定义的新异常重写了 __init__() 方法, 确保你使用所有参数调用 Exception.__init__() ,例如: class CustomError(Exception): def __init__(self, message, status): super().__init__(message, status) self.message = message self.status = status 看上去有点奇怪,不过Exception的默认行为是接受所有传递的参数并将它们以元组形式存储在 .args 属性中. 很多其他函数库和部分Python库默认所有异常都必须有 .args 属性, 因此如果你忽略了这一步,你会发现有些时候你定义的新异常不会按照期望运行。 为了演示 .args 的使用,考虑下下面这个使用内置的 RuntimeError` 异常的交互会话, 注意看raise语句中使用的参数个数是怎样的: >>> try: ... raise RuntimeError('It failed') ... except RuntimeError as e: ... print(e.args) ... ('It failed',) >>> try: ... raise RuntimeError('It failed', 42, 'spam') ... except RuntimeError as e: ... print(e.args) ... ('It failed', 42, 'spam') >>>

景凌凯 2020-04-17 18:00:58 0 浏览量 回答数 0

回答

你的getData函数返回一个元组,这就是为什么两列都有lat和lon的原因。一种解决方法可能是按如下方式对此函数进行参数化:def getData(l_zwsid, a_addr, a_zip, axis='lat'):valid = ['lat', 'lon'] if axis not in valid: raise ValueError(f'axis must be one of {valid}') ... if axis == 'lat': return latitude else: return longitude然而,这不会提高效率会使其更慢。您的主要开销来自于为DataFrame中的每一行进行API调用,因此您受到网络性能的限制。

一码平川MACHEL 2019-12-02 01:54:30 0 浏览量 回答数 0

问题

python的获取详细的报错异常内容?报错

爱吃鱼的程序员 2020-06-22 19:08:25 0 浏览量 回答数 1

回答

如果你想创建一个全新的实例属性,可以通过一个描述器类的形式来定义它的功能。下面是一个例子: # Descriptor attribute for an integer type-checked attribute class Integer: def __init__(self, name): self.name = name def __get__(self, instance, cls): if instance is None: return self else: return instance.__dict__[self.name] def __set__(self, instance, value): if not isinstance(value, int): raise TypeError('Expected an int') instance.__dict__[self.name] = value def __delete__(self, instance): del instance.__dict__[self.name] 一个描述器就是一个实现了三个核心的属性访问操作(get, set, delete)的类, 分别为 __get__() 、__set__() 和 __delete__() 这三个特殊的方法。 这些方法接受一个实例作为输入,之后相应的操作实例底层的字典。 为了使用一个描述器,需将这个描述器的实例作为类属性放到一个类的定义中。例如: class Point: x = Integer('x') y = Integer('y') def __init__(self, x, y): self.x = x self.y = y 当你这样做后,所有对描述器属性(比如x或y)的访问会被 __get__() 、__set__() 和 __delete__() 方法捕获到。例如: >>> p = Point(2, 3) >>> p.x # Calls Point.x.__get__(p,Point) 2 >>> p.y = 5 # Calls Point.y.__set__(p, 5) >>> p.x = 2.3 # Calls Point.x.__set__(p, 2.3) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "descrip.py", line 12, in __set__ raise TypeError('Expected an int') TypeError: Expected an int >>> 作为输入,描述器的每一个方法会接受一个操作实例。 为了实现请求操作,会相应的操作实例底层的字典(__dict__属性)。 描述器的 self.name 属性存储了在实例字典中被实际使用到的key。

哦哦喔 2020-04-17 15:03:33 0 浏览量 回答数 0

问题

是否可以全局设置元类,使其适用于默认情况下创建的所有类?

is大龙 2020-03-24 14:42:34 1 浏览量 回答数 1

回答

在类中定义装饰器初看上去好像很奇怪,但是在标准库中有很多这样的例子。 特别的,@property 装饰器实际上是一个类,它里面定义了三个方法 getter(), setter(), deleter() , 每一个方法都是一个装饰器。例如: class Person: # Create a property instance first_name = property() # Apply decorator methods @first_name.getter def first_name(self): return self._first_name @first_name.setter def first_name(self, value): if not isinstance(value, str): raise TypeError('Expected a string') self._first_name = value 它为什么要这么定义的主要原因是各种不同的装饰器方法会在关联的 property 实例上操作它的状态。 因此,任何时候只要你碰到需要在装饰器中记录或绑定信息,那么这不失为一种可行方法。 在类中定义装饰器有个难理解的地方就是对于额外参数 self 或 cls 的正确使用。 尽管最外层的装饰器函数比如 decorator1() 或 decorator2() 需要提供一个 self 或 cls 参数, 但是在两个装饰器内部被创建的 wrapper() 函数并不需要包含这个 self 参数。 你唯一需要这个参数是在你确实要访问包装器中这个实例的某些部分的时候。其他情况下都不用去管它。 对于类里面定义的包装器还有一点比较难理解,就是在涉及到继承的时候。 例如,假设你想让在A中定义的装饰器作用在子类B中。你需要像下面这样写: class B(A): @A.decorator2 def bar(self): pass 也就是说,装饰器要被定义成类方法并且你必须显式的使用父类名去调用它。 你不能使用 @B.decorator2 ,因为在方法定义时,这个类B还没有被创建。

景凌凯 2020-04-17 17:42:44 0 浏览量 回答数 0

问题

继承自python的'File'类并定义自定义行为 - python2和3

一码平川MACHEL 2019-12-01 19:32:05 419 浏览量 回答数 1

回答

因为path是属性的名称,所以需要一个单独的变量来存储实际的值;通常命名为_path(带下划线)。否则,你的getter会递归地调用自身setter也是如此;行自我。setter中的path = c是导致对setter的递归调用的原因,因为setter像self一样处理所有的赋值。路径= .... 下面是一个如何正确做这件事的例子: class Example: def __init__(self, foo): self.foo = foo @property def foo(self): return self._foo @foo.setter def foo(self, value): if value >= 0: self._foo = value else: raise ValueError() 注意,带下划线的_foo只需要在getter和setter中使用;其他方法,比如_init__可以也应该使用foo(没有下划线)来调用getter或setter。

kun坤 2019-12-25 22:22:44 0 浏览量 回答数 0

回答

许多Python初学者都会问:我应该学习哪个版本的Python。对于这个问题,我的回答通常是“先选择一个最适合你的Python教程,教程中使用哪个版本的Python,你就用那个版本。等学得差不多了,再来研究不同版本之间的差别”。 许多Python初学者都会问:我应该学习哪个版本的Python。对于这个问题,我的回答通常是“先选择一个最适合你的Python教程,教程中使用哪个版本的Python,你就用那个版本。等学得差不多了,再来研究不同版本之间的差别”。但如果想要用Python开发一个新项目,那么该如何选择Python版本呢?我可以负责任的说,大部分Python库都同时支持Python 2.7.x和3.x版本的,所以不论选择哪个版本都是可以的。但为了在使用Python时避开某些版本中一些常见的陷阱,或需要移植某个Python项目时,依然有必要了解一下Python两个常见版本之间的主要区别。__future__模块Python 3.x引入了一些与Python 2不兼容的关键字和特性,在Python 2中,可以通过内置的__future__模块导入这些新内容。如果你希望在Python 2环境下写的代码也可以在Python 3.x中运行,那么建议使用__future__模块。例如,如果希望在Python 2中拥有Python 3.x的整数除法行为,可以通过下面的语句导入相应的模块。from future import division 下表列出了__future__中其他可导入的特性:特性 可选版本 强制版本 效果nested_scopes 2.1.0b1 2.2 PEP 227:Statically Nested Scopesgenerators 2.2.0a1 2.3 PEP 255:Simple Generatorsdivision 2.2.0a2 3.0 PEP 238:Changing the Division Operatorabsolute_import 2.5.0a1 3.0 PEP 328:Imports: Multi-Line and Absolute/Relativewith_statement 2.5.0a1 2.6 PEP 343:The “with” Statementprint_function 2.6.0a2 3.0 PEP 3105:Make print a functionunicode_literals 2.6.0a2 3.0 PEP 3112:Bytes literals in Python 3000(来源: https://docs.python.org/2/library/future.html)示例:from platform import python_version print函数虽然print语法是Python 3中一个很小的改动,且应该已经广为人知,但依然值得提一下:Python 2中的print语句被Python 3中的print()函数取代,这意味着在Python 3中必须用括号将需要输出的对象括起来。在Python 2中使用额外的括号也是可以的。但反过来在Python 3中想以Python2的形式不带括号调用print函数时,会触发SyntaxError。Python 2print 'Python', python_version() print 'Hello, World!' print('Hello, World!') print "text", ; print 'print more text on the same line' Python 2.7.6 Hello, World! Hello, World! text print more text on the same line Python 3print('Python', python_version()) print('Hello, World!') print("some text,", end="") print(' print more text on the same line') Python 3.4.1 Hello, World! some text, print more text on the same line print 'Hello, World!' File "", line 1 print 'Hello, World!' ^ SyntaxError: invalid syntax 注意:在Python中,带不带括号输出”Hello World”都很正常。但如果在圆括号中同时输出多个对象时,就会创建一个元组,这是因为在Python 2中,print是一个语句,而不是函数调用。print 'Python', python_version() print('a', 'b') print 'a', 'b' Python 2.7.7 ('a', 'b') a b 整数除法由于人们常常会忽视Python 3在整数除法上的改动(写错了也不会触发Syntax Error),所以在移植代码或在Python 2中执行Python 3的代码时,需要特别注意这个改动。所以,我还是会在Python 3的脚本中尝试用float(3)/2或 3/2.0代替3/2,以此来避免代码在Python 2环境下可能导致的错误(或与之相反,在Python 2脚本中用from future import division来使用Python 3的除法)。Python 2print 'Python', python_version() print '3 / 2 =', 3 / 2 print '3 // 2 =', 3 // 2 print '3 / 2.0 =', 3 / 2.0 print '3 // 2.0 =', 3 // 2.0 Python 2.7.6 3 / 2 = 1 3 // 2 = 1 3 / 2.0 = 1.5 3 // 2.0 = 1.0 Python 3print('Python', python_version()) print('3 / 2 =', 3 / 2) print('3 // 2 =', 3 // 2) print('3 / 2.0 =', 3 / 2.0) print('3 // 2.0 =', 3 // 2.0) Python 3.4.1 3 / 2 = 1.5 3 // 2 = 1 3 / 2.0 = 1.5 3 // 2.0 = 1.0 UnicodePython 2有基于ASCII的str()类型,其可通过单独的unicode()函数转成unicode类型,但没有byte类型。而在Python 3中,终于有了Unicode(utf-8)字符串,以及两个字节类:bytes和bytearrays。Python 2print 'Python', python_version() Python 2.7.6 print type(unicode('this is like a python3 str type')) print type(b'byte type does not exist') print 'they are really' + b' the same' they are really the same print type(bytearray(b'bytearray oddly does exist though')) Python 3print('Python', python_version()) print('strings are now utf-8 u03BCnicou0394é!') Python 3.4.1 strings are now utf-8 μnicoΔé! print('Python', python_version(), end="") print(' has', type(b' bytes for storing data')) Python 3.4.1 has print('and Python', python_version(), end="") print(' also has', type(bytearray(b'bytearrays'))) and Python 3.4.1 also has 'note that we cannot add a string' + b'bytes for data' TypeError Traceback (most recent call last) in () ----> 1 'note that we cannot add a string' + b'bytes for data' TypeError: Can't convert 'bytes' object to str implicitly xrange在Python 2.x中,经常会用xrange()创建一个可迭代对象,通常出现在“for循环”或“列表/集合/字典推导式”中。这种行为与生成器非常相似(如”惰性求值“),但这里的xrange-iterable无尽的,意味着可能在这个xrange上无限迭代。由于xrange的“惰性求知“特性,如果只需迭代一次(如for循环中),range()通常比xrange()快一些。不过不建议在多次迭代中使用range(),因为range()每次都会在内存中重新生成一个列表。在Python 3中,range()的实现方式与xrange()函数相同,所以就不存在专用的xrange()(在Python 3中使用xrange()会触发NameError)。import timeit n = 10000 def test_range(n): return for i in range(n): pass def test_xrange(n): for i in xrange(n): pass Python 2print 'Python', python_version() print 'ntiming range()' %timeit test_range(n) print 'nntiming xrange()' %timeit test_xrange(n) Python 2.7.6 timing range() 1000 loops, best of 3: 433 µs per loop timing xrange() 1000 loops, best of 3: 350 µs per loop Python 3print('Python', python_version()) print('ntiming range()') %timeit test_range(n) Python 3.4.1 timing range() 1000 loops, best of 3: 520 µs per loop print(xrange(10)) NameError Traceback (most recent call last) in () ----> 1 print(xrange(10)) NameError: name 'xrange' is not defined Python 3中的range对象中的__contains__方法另一个值得一提的是,在Python 3.x中,range有了一个新的__contains__方法。__contains__方法可以有效的加快Python 3.x中整数和布尔型的“查找”速度。x = 10000000 def val_in_range(x, val): return val in range(x) def val_in_xrange(x, val): return val in xrange(x) print('Python', python_version()) assert(val_in_range(x, x/2) == True) assert(val_in_range(x, x//2) == True) %timeit val_in_range(x, x/2) %timeit val_in_range(x, x//2) Python 3.4.1 1 loops, best of 3: 742 ms per loop 1000000 loops, best of 3: 1.19 µs per loop 根据上面的timeit的结果,查找整数比查找浮点数要快大约6万倍。但由于Python 2.x中的range或xrange没有__contains__方法,所以在Python 2中的整数和浮点数的查找速度差别不大。print 'Python', python_version() assert(val_in_xrange(x, x/2.0) == True) assert(val_in_xrange(x, x/2) == True) assert(val_in_range(x, x/2) == True) assert(val_in_range(x, x//2) == True) %timeit val_in_xrange(x, x/2.0) %timeit val_in_xrange(x, x/2) %timeit val_in_range(x, x/2.0) %timeit val_in_range(x, x/2) Python 2.7.7 1 loops, best of 3: 285 ms per loop 1 loops, best of 3: 179 ms per loop 1 loops, best of 3: 658 ms per loop 1 loops, best of 3: 556 ms per loop 下面的代码证明了Python 2.x中没有__contain__方法:print('Python', python_version()) range.__contains__ Python 3.4.1 print('Python', python_version()) range.__contains__ Python 2.7.7 AttributeError Traceback (most recent call last) in () 1 print 'Python', python_version() ----> 2 range.__contains__ AttributeError: 'builtin_function_or_method' object has no attribute '__contains__' print('Python', python_version()) xrange.__contains__ Python 2.7.7 AttributeError Traceback (most recent call last) in () 1 print 'Python', python_version() ----> 2 xrange.__contains__ AttributeError: type object 'xrange' has no attribute '__contains__' 关于Python 2中xrange()与Python 3中range()之间的速度差异的一点说明:有读者指出了Python 3中的range()和Python 2中xrange()执行速度有差异。由于这两者的实现方式相同,因此理论上执行速度应该也是相同的。这里的速度差别仅仅是因为Python 3的总体速度就比Python 2慢。def test_while(): i = 0 while i < 20000: i += 1 return print('Python', python_version()) %timeit test_while() Python 3.4.1 %timeit test_while() 100 loops, best of 3: 2.68 ms per loop print 'Python', python_version() %timeit test_while() Python 2.7.6 1000 loops, best of 3: 1.72 ms per loop 触发异常Python 2支持新旧两种异常触发语法,而Python 3只接受带括号的的语法(不然会触发SyntaxError):Python 2print 'Python', python_version()Python 2.7.6 raise IOError, "file error" IOError Traceback (most recent call last) in ()----> 1 raise IOError, "file error" IOError: file error raise IOError("file error") IOError Traceback (most recent call last) in ()----> 1 raise IOError("file error") IOError: file errorPython 3print('Python', python_version())Python 3.4.1raise IOError, "file error"File "", line 1raise IOError, "file error"^SyntaxError: invalid syntaxThe proper way to raise an exception in Python 3:print('Python', python_version())raise IOError("file error")Python 3.4.1 OSError Traceback (most recent call last) in ()1 print('Python', python_version())----> 2 raise IOError("file error") OSError: file error异常处理Python 3中的异常处理也发生了一点变化。在Python 3中必须使用“as”关键字。Python 2print 'Python', python_version()try: let_us_cause_a_NameError except NameError, err: print err, '--> our error message' Python 2.7.6name 'let_us_cause_a_NameError' is not defined --> our error messagePython 3print('Python', python_version())try: let_us_cause_a_NameError except NameError as err: print(err, '--> our error message') Python 3.4.1name 'let_us_cause_a_NameError' is not defined --> our error messagenext()函数和.next()方法由于会经常用到next()(.next())函数(方法),所以还要提到另一个语法改动(实现方面也做了改动):在Python 2.7.5中,函数形式和方法形式都可以使用,而在Python 3中,只能使用next()函数(试图调用.next()方法会触发AttributeError)。Python 2print 'Python', python_version()my_generator = (letter for letter in 'abcdefg')next(my_generator)my_generator.next()Python 2.7.6'b'Python 3print('Python', python_version())my_generator = (letter for letter in 'abcdefg')next(my_generator)Python 3.4.1'a' my_generator.next() AttributeError Traceback (most recent call last) in ()----> 1 my_generator.next() AttributeError: 'generator' object has no attribute 'next'For循环变量与全局命名空间泄漏好消息是:在Python 3.x中,for循环中的变量不再会泄漏到全局命名空间中了!这是Python 3.x中做的一个改动,在“What’s New In Python 3.0”中有如下描述:“列表推导不再支持[… for var in item1, item2, …]这样的语法,使用[… for var in (item1, item2, …)]代替。还要注意列表推导有不同的语义:现在列表推导更接近list()构造器中的生成器表达式这样的语法糖,特别要注意的是,循环控制变量不会再泄漏到循环周围的空间中了。”Python 2print 'Python', python_version() i = 1print 'before: i =', i print 'comprehension: ', [i for i in range(5)] print 'after: i =', iPython 2.7.6before: i = 1comprehension: [0, 1, 2, 3, 4]after: i = 4Python 3print('Python', python_version()) i = 1print('before: i =', i) print('comprehension:', [i for i in range(5)]) print('after: i =', i)Python 3.4.1before: i = 1comprehension: [0, 1, 2, 3, 4]after: i = 1比较无序类型Python 3中另一个优秀的改动是,如果我们试图比较无序类型,会触发一个TypeError。Python 2print 'Python', python_version()print "[1, 2] > 'foo' = ", [1, 2] > 'foo'print "(1, 2) > 'foo' = ", (1, 2) > 'foo'print "[1, 2] > (1, 2) = ", [1, 2] > (1, 2)Python 2.7.6[1, 2] > 'foo' = False(1, 2) > 'foo' = True[1, 2] > (1, 2) = FalsePython 3print('Python', python_version())print("[1, 2] > 'foo' = ", [1, 2] > 'foo')print("(1, 2) > 'foo' = ", (1, 2) > 'foo')print("[1, 2] > (1, 2) = ", [1, 2] > (1, 2)) Python 3.4.1 TypeError Traceback (most recent call last) in ()1 print('Python', python_version())----> 2 print("[1, 2] > 'foo' = ", [1, 2] > 'foo')3 print("(1, 2) > 'foo' = ", (1, 2) > 'foo')4 print("[1, 2] > (1, 2) = ", [1, 2] > (1, 2))TypeError: unorderable types: list() > str()通过input()解析用户的输入幸运的是,Python 3改进了input()函数,这样该函数就会总是将用户的输入存储为str对象。在Python 2中,为了避免读取非字符串类型会发生的一些危险行为,不得不使用raw_input()代替input()。Python 2Python 2.7.6[GCC 4.0.1 (Apple Inc. build 5493)] on darwinType "help", "copyright", "credits" or "license" for more information. my_input = input('enter a number: ') enter a number: 123 type(my_input) my_input = raw_input('enter a number: ') enter a number: 123 type(my_input) Python 3Python 3.4.1[GCC 4.2.1 (Apple Inc. build 5577)] on darwinType "help", "copyright", "credits" or "license" for more information. my_input = input('enter a number: ') enter a number: 123 type(my_input) 返回可迭代对象,而不是列表在xrange一节中可以看到,某些函数和方法在Python中返回的是可迭代对象,而不像在Python 2中返回列表。由于通常对这些对象只遍历一次,所以这种方式会节省很多内存。然而,如果通过生成器来多次迭代这些对象,效率就不高了。此时我们的确需要列表对象,可以通过list()函数简单的将可迭代对象转成列表。Python 2print 'Python', python_version() print range(3)print type(range(3))Python 2.7.6[0, 1, 2]Python 3print('Python', python_version())print(range(3))print(type(range(3)))print(list(range(3)))Python 3.4.1range(0, 3)[0, 1, 2]下面列出了Python 3中其他不再返回列表的常用函数和方法:zip()map()filter()字典的.key()方法字典的.value()方法字典的.item()方法 __future__模块 [回到目录] Python 3.x引入了一些与Python 2不兼容的关键字和特性,在Python 2中,可以通过内置的__future__模块导入这些新内容。如果你希望在Python 2环境下写的代码也可以在Python 3.x中运行,那么建议使用__future__模块。例如,如果希望在Python 2中拥有Python 3.x的整数除法行为,可以通过下面的语句导入相应的模块。 ? 1 from future import division 下表列出了__future__中其他可导入的特性: 特性 可选版本 强制版本 效果 nested_scopes 2.1.0b1 2.2 PEP 227:Statically Nested Scopes generators 2.2.0a1 2.3 PEP 255:Simple Generators division 2.2.0a2 3.0 PEP 238:Changing the Division Operator absolute_import 2.5.0a1 3.0 PEP 328:Imports: Multi-Line and Absolute/Relative with_statement 2.5.0a1 2.6 PEP 343:The “with” Statement print_function 2.6.0a2 3.0 PEP 3105:Make print a function unicode_literals 2.6.0a2 3.0 PEP 3112:Bytes literals in Python 3000 (来源: https://docs.python.org/2/library/future.html) 示例: ? 1 from platform import python_version print函数 [回到目录] 虽然print语法是Python 3中一个很小的改动,且应该已经广为人知,但依然值得提一下:Python 2中的print语句被Python 3中的print()函数取代,这意味着在Python 3中必须用括号将需要输出的对象括起来。 在Python 2中使用额外的括号也是可以的。但反过来在Python 3中想以Python2的形式不带括号调用print函数时,会触发SyntaxError。 Python 2 ? 1234 print 'Python', python_version()print 'Hello, World!'print('Hello, World!')print "text", ; print 'print more text on the same line' ? 1234 Python 2.7.6Hello, World!Hello, World!text print more text on the same line Python 3 ? 12345 print('Python', python_version())print('Hello, World!') print("some text,", end="") print(' print more text on the same line') ? 123 Python 3.4.1Hello, World!some text, print more text on the same line ? 1 print 'Hello, World!' ? File "", line 1print 'Hello, World!'^SyntaxError: invalid syntax 注意: 在Python中,带不带括号输出”Hello World”都很正常。但如果在圆括号中同时输出多个对象时,就会创建一个元组,这是因为在Python 2中,print是一个语句,而不是函数调用。 ? 123 print 'Python', python_version()print('a', 'b')print 'a', 'b' Python 2.7.7('a', 'b')a b 整数除法 [回到目录] 由于人们常常会忽视Python 3在整数除法上的改动(写错了也不会触发Syntax Error),所以在移植代码或在Python 2中执行Python 3的代码时,需要特别注意这个改动。 所以,我还是会在Python 3的脚本中尝试用float(3)/2或 3/2.0代替3/2,以此来避免代码在Python 2环境下可能导致的错误(或与之相反,在Python 2脚本中用from future import division来使用Python 3的除法)。 Python 2 ? 12345 print 'Python', python_version()print '3 / 2 =', 3 / 2print '3 // 2 =', 3 // 2print '3 / 2.0 =', 3 / 2.0print '3 // 2.0 =', 3 // 2.0 Python 2.7.63 / 2 = 13 // 2 = 13 / 2.0 = 1.53 // 2.0 = 1.0 Python 3 ? 12345 print('Python', python_version())print('3 / 2 =', 3 / 2)print('3 // 2 =', 3 // 2)print('3 / 2.0 =', 3 / 2.0)print('3 // 2.0 =', 3 // 2.0) Python 3.4.13 / 2 = 1.53 // 2 = 13 / 2.0 = 1.53 // 2.0 = 1.0 Unicode [回到目录] Python 2有基于ASCII的str()类型,其可通过单独的unicode()函数转成unicode类型,但没有byte类型。 而在Python 3中,终于有了Unicode(utf-8)字符串,以及两个字节类:bytes和bytearrays。 Python 2 ? 1 print 'Python', python_version() Python 2.7.6 ? 1 print type(unicode('this is like a python3 str type')) ? 1 print type(b'byte type does not exist') ? 1 print 'they are really' + b' the same' they are really the same ? 1 print type(bytearray(b'bytearray oddly does exist though')) Python 3 ? 12 print('Python', python_version())print('strings are now utf-8 u03BCnicou0394é!') Python 3.4.1strings are now utf-8 μnicoΔé! ? 12 print('Python', python_version(), end="")print(' has', type(b' bytes for storing data')) Python 3.4.1 has ? 12 print('and Python', python_version(), end="")print(' also has', type(bytearray(b'bytearrays'))) and Python 3.4.1 also has ? 1 'note that we cannot add a string' + b'bytes for data' TypeError Traceback (most recent call last) in ()----> 1 'note that we cannot add a string' + b'bytes for data' TypeError: Can't convert 'bytes' object to str implicitly xrange [回到目录] 在Python 2.x中,经常会用xrange()创建一个可迭代对象,通常出现在“for循环”或“列表/集合/字典推导式”中。 这种行为与生成器非常相似(如”惰性求值“),但这里的xrange-iterable无尽的,意味着可能在这个xrange上无限迭代。 由于xrange的“惰性求知“特性,如果只需迭代一次(如for循环中),range()通常比xrange()快一些。不过不建议在多次迭代中使用range(),因为range()每次都会在内存中重新生成一个列表。 在Python 3中,range()的实现方式与xrange()函数相同,所以就不存在专用的xrange()(在Python 3中使用xrange()会触发NameError)。 ? 12345678910 import timeit n = 10000def test_range(n): return for i in range(n): pass def test_xrange(n): for i in xrange(n): pass Python 2 ? 1234567 print 'Python', python_version() print 'ntiming range()'%timeit test_range(n) print 'nntiming xrange()'%timeit test_xrange(n) Python 2.7.6 timing range()1000 loops, best of 3: 433 µs per loop timing xrange()1000 loops, best of 3: 350 µs per loop Python 3 ? 1234 print('Python', python_version()) print('ntiming range()')%timeit test_range(n) Python 3.4.1 timing range()1000 loops, best of 3: 520 µs per loop ? 1 print(xrange(10)) NameError Traceback (most recent call last)in ()----> 1 print(xrange(10)) NameError: name 'xrange' is not defined Python 3中的range对象中的__contains__方法 另一个值得一提的是,在Python 3.x中,range有了一个新的__contains__方法。__contains__方法可以有效的加快Python 3.x中整数和布尔型的“查找”速度。 ? 123456789101112 x = 10000000def val_in_range(x, val): return val in range(x) def val_in_xrange(x, val): return val in xrange(x) print('Python', python_version())assert(val_in_range(x, x/2) == True)assert(val_in_range(x, x//2) == True)%timeit val_in_range(x, x/2)%timeit val_in_range(x, x//2) Python 3.4.11 loops, best of 3: 742 ms per loop1000000 loops, best of 3: 1.19 µs per loop 根据上面的timeit的结果,查找整数比查找浮点数要快大约6万倍。但由于Python 2.x中的range或xrange没有__contains__方法,所以在Python 2中的整数和浮点数的查找速度差别不大。 ? 12345678910 print 'Python', python_version() assert(val_in_xrange(x, x/2.0) == True)assert(val_in_xrange(x, x/2) == True)assert(val_in_range(x, x/2) == True)assert(val_in_range(x, x//2) == True)%timeit val_in_xrange(x, x/2.0)%timeit val_in_xrange(x, x/2)%timeit val_in_range(x, x/2.0)%timeit val_in_range(x, x/2) Python 2.7.71 loops, best of 3: 285 ms per loop1 loops, best of 3: 179 ms per loop1 loops, best of 3: 658 ms per loop1 loops, best of 3: 556 ms per loop 下面的代码证明了Python 2.x中没有__contain__方法: ? 12 print('Python', python_version())range.__contains__ Python 3.4.1 ? 12 print('Python', python_version())range.__contains__ Python 2.7.7 AttributeError Traceback (most recent call last) in ()1 print 'Python', python_version()----> 2 range.__contains__ AttributeError: 'builtin_function_or_method' object has no attribute '__contains__' ? 12 print('Python', python_version())xrange.__contains__ Python 2.7.7 AttributeError Traceback (most recent call last)in ()1 print 'Python', python_version()----> 2 xrange.__contains__ AttributeError: type object 'xrange' has no attribute '__contains__' 关于Python 2中xrange()与Python 3中range()之间的速度差异的一点说明: 有读者指出了Python 3中的range()和Python 2中xrange()执行速度有差异。由于这两者的实现方式相同,因此理论上执行速度应该也是相同的。这里的速度差别仅仅是因为Python 3的总体速度就比Python 2慢。 ? 12345 def test_while(): i = 0 while i < 20000: i += 1 return ? 12 print('Python', python_version())%timeit test_while() Python 3.4.1%timeit test_while()100 loops, best of 3: 2.68 ms per loop ? 12 print 'Python', python_version()%timeit test_while() Python 2.7.61000 loops, best of 3: 1.72 ms per loop 触发异常 [回到目录] Python 2支持新旧两种异常触发语法,而Python 3只接受带括号的的语法(不然会触发SyntaxError): Python 2 ? 1 print 'Python', python_version() Python 2.7.6 ? 1 raise IOError, "file error" IOError Traceback (most recent call last) in ()----> 1 raise IOError, "file error" IOError: file error ? 1 raise IOError("file error") IOError Traceback (most recent call last) in ()----> 1 raise IOError("file error") IOError: file error Python 3 ? 1 print('Python', python_version()) Python 3.4.1 ? 1 raise IOError, "file error" File "", line 1raise IOError, "file error"^SyntaxError: invalid syntaxThe proper way to raise an exception in Python 3: ? 12 print('Python', python_version())raise IOError("file error") Python 3.4.1 OSError Traceback (most recent call last) in ()1 print('Python', python_version())----> 2 raise IOError("file error") OSError: file error 异常处理 [回到目录] Python 3中的异常处理也发生了一点变化。在Python 3中必须使用“as”关键字。 Python 2 ? 12345 print 'Python', python_version()try: let_us_cause_a_NameErrorexcept NameError, err: print err, '--> our error message' Python 2.7.6name 'let_us_cause_a_NameError' is not defined --> our error message Python 3 ? 12345 print('Python', python_version())try: let_us_cause_a_NameErrorexcept NameError as err: print(err, '--> our error message') Python 3.4.1name 'let_us_cause_a_NameError' is not defined --> our error message next()函数和.next()方法 [回到目录] 由于会经常用到next()(.next())函数(方法),所以还要提到另一个语法改动(实现方面也做了改动):在Python 2.7.5中,函数形式和方法形式都可以使用,而在Python 3中,只能使用next()函数(试图调用.next()方法会触发AttributeError)。 Python 2 ? 1234 print 'Python', python_version()my_generator = (letter for letter in 'abcdefg')next(my_generator)my_generator.next() Python 2.7.6'b' Python 3 ? 123 print('Python', python_version())my_generator = (letter for letter in 'abcdefg')next(my_generator) Python 3.4.1'a' ? 1 my_generator.next() AttributeError Traceback (most recent call last) in ()----> 1 my_generator.next() AttributeError: 'generator' object has no attribute 'next' For循环变量与全局命名空间泄漏 [回到目录] 好消息是:在Python 3.x中,for循环中的变量不再会泄漏到全局命名空间中了! 这是Python 3.x中做的一个改动,在“What's New In Python 3.0”中有如下描述: “列表推导不再支持[... for var in item1, item2, ...]这样的语法,使用[... for var in (item1, item2, ...)]代替。还要注意列表推导有不同的语义:现在列表推导更接近list()构造器中的生成器表达式这样的语法糖,特别要注意的是,循环控制变量不会再泄漏到循环周围的空间中了。” Python 2 ? 12345678 print 'Python', python_version() i = 1print 'before: i =', i print 'comprehension: ', [i for i in range(5)] print 'after: i =', i Python 2.7.6before: i = 1comprehension: [0, 1, 2, 3, 4]after: i = 4 Python 3 ? 12345678 print('Python', python_version()) i = 1print('before: i =', i) print('comprehension:', [i for i in range(5)]) print('after: i =', i) Python 3.4.1before: i = 1comprehension: [0, 1, 2, 3, 4]after: i = 1 比较无序类型 [回到目录] Python 3中另一个优秀的改动是,如果我们试图比较无序类型,会触发一个TypeError。 Python 2 ? 1234 print 'Python', python_version()print "[1, 2] > 'foo' = ", [1, 2] > 'foo'print "(1, 2) > 'foo' = ", (1, 2) > 'foo'print "[1, 2] > (1, 2) = ", [1, 2] > (1, 2) Python 2.7.6[1, 2] > 'foo' = False(1, 2) > 'foo' = True[1, 2] > (1, 2) = False Python 3 ? 1234 print('Python', python_version())print("[1, 2] > 'foo' = ", [1, 2] > 'foo')print("(1, 2) > 'foo' = ", (1, 2) > 'foo')print("[1, 2] > (1, 2) = ", [1, 2] > (1, 2)) Python 3.4.1 TypeError Traceback (most recent call last) in ()1 print('Python', python_version())----> 2 print("[1, 2] > 'foo' = ", [1, 2] > 'foo')3 print("(1, 2) > 'foo' = ", (1, 2) > 'foo')4 print("[1, 2] > (1, 2) = ", [1, 2] > (1, 2))TypeError: unorderable types: list() > str() 通过input()解析用户的输入 [回到目录] 幸运的是,Python 3改进了input()函数,这样该函数就会总是将用户的输入存储为str对象。在Python 2中,为了避免读取非字符串类型会发生的一些危险行为,不得不使用raw_input()代替input()。 Python 2 ? 1234567891011121314151617 Python 2.7.6[GCC 4.0.1 (Apple Inc. build 5493)] on darwinType "help", "copyright", "credits" or "license" for more information. my_input = input('enter a number: ') enter a number: 123 type(my_input) my_input = raw_input('enter a number: ') enter a number: 123 type(my_input) Python 3 ? 12345678 Python 3.4.1[GCC 4.2.1 (Apple Inc. build 5577)] on darwinType "help", "copyright", "credits" or "license" for more information. my_input = input('enter a number: ') enter a number: 123 type(my_input) 返回可迭代对象,而不是列表 [回到目录] 在xrange一节中可以看到,某些函数和方法在Python中返回的是可迭代对象,而不像在Python 2中返回列表。 由于通常对这些对象只遍历一次,所以这种方式会节省很多内存。然而,如果通过生成器来多次迭代这些对象,效率就不高了。 此时我们的确需要列表对象,可以通过list()函数简单的将可迭代对象转成列表。 Python 2 ? 1234 print 'Python', python_version() print range(3)print type(range(3)) Python 2.7.6[0, 1, 2] Python 3 ? 1234 print('Python', python_version())print(range(3))print(type(range(3)))print(list(range(3))) Python 3.4.1range(0, 3)[0, 1, 2] 下面列出了Python 3中其他不再返回列表的常用函数和方法:•zip()•map()•filter()•字典的.key()方法•字典的.value()方法•字典的.item()方法 更多关于Python 2和Python 3的文章 [回到目录] 下面列出了其他一些可以进一步了解Python 2和Python 3的优秀文章, //迁移到 Python 3•Should I use Python 2 or Python 3 for my development activity?•What's New In Python 3.0•Porting to Python 3•Porting Python 2 Code to Python 3•How keep Python 3 moving forward // 对Python 3的褒与贬•10 awesome features of Python that you can't use because you refuse to upgrade to Python 3•关于你不想知道的所有Python3 unicode特性•Python 3 正在毁灭 Python•Python 3 能振兴 Python•Python 3 is fine

xuning715 2019-12-02 01:10:35 0 浏览量 回答数 0

回答

使用 abc 模块可以很轻松的定义抽象基类: from abc import ABCMeta, abstractmethod class IStream(metaclass=ABCMeta): @abstractmethod def read(self, maxbytes=-1): pass @abstractmethod def write(self, data): pass 抽象类的一个特点是它不能直接被实例化,比如你想像下面这样做是不行的: a = IStream() # TypeError: Can't instantiate abstract class # IStream with abstract methods read, write 抽象类的目的就是让别的类继承它并实现特定的抽象方法: class SocketStream(IStream): def read(self, maxbytes=-1): pass def write(self, data): pass 抽象基类的一个主要用途是在代码中检查某些类是否为特定类型,实现了特定接口: def serialize(obj, stream): if not isinstance(stream, IStream): raise TypeError('Expected an IStream') pass 除了继承这种方式外,还可以通过注册方式来让某个类实现抽象基类: import io # Register the built-in I/O classes as supporting our interface IStream.register(io.IOBase) # Open a normal file and type check f = open('foo.txt') isinstance(f, IStream) # Returns True @abstractmethod 还能注解静态方法、类方法和 properties 。 你只需保证这个注解紧靠在函数定义前即可: class A(metaclass=ABCMeta): @property @abstractmethod def name(self): pass @name.setter @abstractmethod def name(self, value): pass @classmethod @abstractmethod def method1(cls): pass @staticmethod @abstractmethod def method2(): pass

哦哦喔 2020-04-17 15:05:24 0 浏览量 回答数 0

问题

如何添加对函数的调用?

一码平川MACHEL 2019-12-01 19:32:04 424 浏览量 回答数 1

回答

Python中没有像C++中public和private这些关键字来区别公有属性和私有属性。它是以属性命名方式来区分,如果在属性名前面加了2个下划线'__',则表明该属性是私有属性,否则为公有属性(方法也是一样,方法名前面加了2个下划线的话表示该方法是私有的,否则为公有的)。 class Plane(object): def __init__(self): self.mA = 100 self.mB = 200 self.__mC = 300  p  = Plane() 但是类的方法可以封装__私有属性,如下可以通过Student.get_name访问self.__name class Student(object): # 类名的括号里写继承的类,如果没有则写object,这是所有类都要继承的类     school = '清华大学' # 直接在类中定义的属性为类属性,归Student类所有,所有实例都可以访问到,但是与java的静态变量不同,如果一个实例改变了school的值,那么这个新值就生效,且只对这一个实例生效     def __init__(self, name, score): # 只要是class中定义的函数,第一个参数都要写self,并且调用时第一个参数都不必传                                     # init 是特殊函数,在创建类时会调用,相当于java的构造函数        self.__name = name # 可以直接self.新的变量名,注意,两个下划线开头的变量名为私有变量,不允许外部访问,但可以通过get和set方法访问和赋值        self.__score = score # 以两个下划线开头且以两个下划线结尾的变量为特殊变量,特殊变量不是私有变量,允许外部访问,因此起变量名时不要起成这种特殊变量的格式     def get_name(self):        return self.__name     def get_score(self):        return self.__score     def set_score(self, score):        if 0 <= score <= 100:            self.__score = score        else:            raise ValueError('bad score') # 手动抛出异常     def get_grade(self):        if self.__score >= 90:            return 'A'        elif self.__score >= 60:            return 'B'        else:            return 'C'

游客drl6uevi2k7uk 2019-12-02 01:57:43 0 浏览量 回答数 0

问题

ParamManager API使用方法

猫饭先生 2019-12-01 21:25:47 1046 浏览量 回答数 0

问题

PyODPS脚本任务不定时出现 IncompleteRead问题

unliklll 2019-12-01 19:44:02 1065 浏览量 回答数 1

回答

来自@Jesse Rusak 的回答: Objective-C 委托就是已被指定为另一个委托的对象,没有特殊的创建过程,你只要定义一个实现你感兴趣的委托方法的类就可以。(虽然委托使用正式协议,但你必须得声明委托来执行该协议,如下所示)例如,假设你有个NSWindow。如果你想要实现他的委托的 windowDidMove: 方法,你可以创建一个这样的类: @implementation MyClass (void)windowDidMove:(NSNotification*)notification { // ... } @end然后创建一个MyClass的实例并制定为window的委托: MyClass *myDelegate = [[MyClass alloc] init];[window setDelegate: myDelegate];在NSWindow方面, 可能有类似于此的代码使用 respondsToSelector: 来看委托是否响应windowDidMove:信息,如何合适就发送。 if([[self delegate] respondsToSelector:@selector(windowDidMove:)]) { [[self delegate] windowDidMove:notification]; }委托资源本身是典型声明的weak(ARC)或assign(预ARC)来避免循环,因为对象委托经常持有强引用该对象(例如,一个视图控制器通常包含视图委托)要定义自己的委托,你需要在某个地方声明方法。有两个基本的方法,苹果的文档协议有讨论过. 1) 一个非正式的协议 这个就和NSWindow差不多,在NSObject的类别实现。例如,继续上面的例子,这是从NSWindow.h:转述的: @interface NSObject(NSWindowNotifications) (void)windowDidMove:(NSNotification *)notification;// ... 其他方法 @end就像上面描述的那样,当调用这个函数的时候,你会使用-respondsToSelector:,委托简单的实现此方法,就完成了。这个方法在苹果的库里是直接常见的,但是新的代码应该是用下面的更现代的方法。 2)一个正式的协议 新的选择是声明一个正式的协议。声明应该像这个样子: @protocol NSWindowNotifications @optional (void)windowDidMove:(NSNotification *)notification;// ...其他方法 @end这类似于一个借口或者抽象基类,因为这为委托建立了一个特殊的类型,这种情况下是NSWindowNotifications。委托执行者应该采用这个协议: @interface MyDelegate // ...@end然后再协议中执行方法。对于诸如@optional(就和大多数委托方法一样)在协议中声明的方法,你仍然需要在调用特殊方法之前检查-respondsToSelector:。苹果建议这种方法,因为这个更精确,不会和NSObject弄混,并且提供更好的工具支持。 优化速度 代替检查委托是否响应选择器,你可以在设置委托时存储相关信息。使用bitfield是一个非常清晰的方法,如下: @protocol SomethingDelegate @optional (void)something:(id)something didFinishLoadingItem:(id)item; (void)something:(id)something didFailWithError:(NSError *)error;@end @interface Something : NSObject@property (nonatomic, weak) id delegate;@end @implementation Something { struct { unsigned int didFinishLoadingItem:1; unsigned int didFailWithError:1; } delegateRespondsTo;}@synthesize delegate; (void)setDelegate:(id )aDelegate {if (delegate != aDelegate) { delegate = aDelegate;delegateRespondsTo.didFinishLoadingItem = [delegate respondsToSelector:@selector(something:didFinishLoadingItem:)]; delegateRespondsTo.didFailWithError = [delegate respondsToSelector:@selector(something:didFailWithError:)];} }@end然后,在正文里,可以通过访问delegateRespondsTo来检查委托处理邮件,而不是一遍又一遍的发送-respondsToSelector:。 来自@Tibidabo 上面的方法很厉害!但是如果你想在1分钟之内解决问题可以尝试一下这个:MyClass.h文件应该像这个样子(用评论添加委托行) import @class MyClass; //定义类,这样协议可以看到MyClass@protocol MyClassDelegate //定义委托协议 (void) myClassDelegateMethod: (MyClass *) sender; //定义在另一个类里实现的委托方法@end //结束协议 @interface MyClass : NSObject {}@property (nonatomic, weak) id delegate; //定义 MyClassDelegate为委托 @endMyClass.m 文件应该像这样: import "MyClass.h" @implementation MyClass @synthesize delegate; //综合MyClassDelegate 委托 (void) myMethodToDoStuff {[self.delegate myClassDelegateMethod:self]; //这个会调用在其他类里实现的方法 } @end为了在其他的类里使用委托(本情况是UIViewController调用MyVC)MyVC.h: import "MyClass.h" @interface MyVC:UIViewController { //make it a delegate for MyClassDelegate}MyVC.m: myClass.delegate = self; //设置委托至自身的某个地方执行委托方法: (void) myClassDelegateMethod: (MyClass *) sender { NSLog(@"Delegates are great!"); } 来自@umop 当用正式的协议方法创建委托支持时,我发现可以确保正确的类型检查(虽然是运行时间,不是编译时间),通过添加如下代码: if (![delegate conformsToProtocol:@protocol(MyDelegate)]) { [NSException raise:@"MyDelegate Exception" format:@"Parameter does not conform to MyDelegate protocol at line %d", (int)__LINE__]; }在你的委托访问(setDelegate)代码,这个能将错误最小化。 来自@Tom Andersen的回答 或许更多的是在于你所缺少的行。如果从C++的视角来看,委托需要一点时间适应,但是基本上“他们只是工作”。委托实现的方式是:设置NSWindow的委托对象,但是对象只为一个或几个可能的委托方法执行。所以会发生一些事,NSWindow想要调用对象,它只使用Objective-c的respondsToSelector方法来决定对象是否被调用,然后再调用。这就是objective-c的实现方式——根据需求寻找方法。用你自己的对象实现这一点是非常琐碎的,没有什么特别的事情,你甚至可以为让一个实例有27个对象的NSArray,完全不同类型的对象,其中只有18个有-(void)setToBue;方法,其他的9个没有。所以在18个需要完成的调用setToBlue,就像这样: for (id anObject in myArray){ if ([anObject respondsToSelector:@selector(@"setToBlue")]) [anObject setToBlue]; }另外,委托是不保留的,所以需要在MyClass dealloc方法中将委托设置为nil。 来自@RDC 的回答: 请看下面的教程是如何一步一步介绍iOS中的委托的。 iOS中的委托我创建了两个 ViewControllers (从一个给另一个发送) FirstViewController 执行委托(提供数据). SecondViewController声明委托(接收数据).

a123456678 2019-12-02 03:13:13 0 浏览量 回答数 0
阿里云大学 云服务器ECS com域名 网站域名whois查询 开发者平台 小程序定制 小程序开发 国内短信套餐包 开发者技术与产品 云数据库 图像识别 开发者问答 阿里云建站 阿里云备案 云市场 万网 阿里云帮助文档 免费套餐 开发者工具 云栖号物联网 小程序开发制作 视频内容分析 企业网站制作 视频集锦 代理记账服务 2020阿里巴巴研发效能峰会 企业建站模板 云效成长地图 高端建站 云栖号弹性计算 阿里云云栖号 云栖号案例 云栖号直播