网站首页 > 文章中心 > 其它

python3函数性能

作者:小编 更新时间:2023-09-06 15:17:13 浏览量:189人看过

「Python3基础」函数

表示一个功能,函数定义着是提供功能的人,函数调用者是使用功能的人.

print:打印功能,将括号中的内容,显示到终端.

python3函数性能-图1

将括号中的内容显示在控制台.

input:输入功能,从终端中获取输入的信息,存到程序变量当中

作用:将用户输入的内容赋值给变量

第一个字符必须是字母表中字母或下划线 _ .

标识符的其他的部分由字母、数字和下划线组成.

标识符对大小写敏感.

python最具特色的就是使用缩进来表示代码块,不需要使用大括号 {} .

缩进的空格数是可变的,但是同一个代码块的语句必须包含相同的缩进空格数.实例如下:

后端编程Python3-调试、测试和性能剖析(下)

单元测试(Unit Testing)

为程序编写测试——如果做的到位——有助于减少bug的出现,并可以提高我们对程序按预期目标运行的信心.通常,测试并不能保证正确性,因为对大多数程序而言, 可能的输入范围以及可能的计算范围是如此之大,只有其中最小的一部分能被实际地进 行测试.尽管如此,通过仔细地选择测试的方法和目标,可以提高代码的质量.

大量不同类型的测试都可以进行,比如可用性测试、功能测试以及整合测试等.这里, 我们只讲单元测试一对单独的函数、类与方法进行测试,确保其符合预期的行为.

TDD的一个关键点是,当我们想添加一个功能时——比如为类添加一个方法—— 我们首次为其编写一个测试用例.当然,测试将失败,因为我们还没有实际编写该方法.现在,我们编写该方法,一旦方法通过了测试,就可以返回所有测试,确保我们新添加的代码没有任何预期外的副作用.一旦所有测试运行完毕(包括我们为新功能编写的测试),就可以对我们的代码进行检查,并有理有据地相信程序行为符合我们的期望——当然,前提是我们的测试是适当的.

比如,我们编写了一个函数,该函数在特定的索引位置插入一个字符串,可以像下面这样开始我们的TDD:

def insert_at(string, position, insert):

"""Returns a copy of string with insert inserted at the position

string = "ABCDE"

result =[]

... result.append(insert_at(string, i,"-"))

['ABC-DE', 'ABCD-E', '-ABCDE','A-BCDE', 'AB-CDE']

['ABC-DE', 'ABCD-E', 'ABCDE-', 'ABCDE-']

"""

return string

对不返回任何参数的函数或方法(通常返回None),我们通常赋予其由pass构成的一个suite,对那些返回值被试用的,我们或者返回一个常数(比如0),或者某个不变的参数——这也是我们这里所做的.(在更复杂的情况下,返回fake对象可能更有用一一对这样的类,提供mock对象的第三方模块是可用的.)

运行doctest时会失败,并列出每个预期内的字符串('ABCD-EF'、'ABCDE-F' 等),及其实际获取的字符串(所有的都是'ABCD-EF').一旦确定doctest是充分的和正确的,就可以编写该函数的主体部分,在本例中只是简单的return string[:position] + insert+string[position:].(如果我们编写的是 return string[:position] + insert,之后复制 string [:position]并将其粘贴在末尾以便减少一些输入操作,那么doctest会立即提示错误.)

Python的标准库提供了两个单元测试模块,一个是doctest,这里和前面都简单地提到过,另一个是unittest.此外,还有一些可用于Python的第三方测试工具.其中最著名的两个是nose (code.google.com/p/python-nose)与py.test (codespeak.net/py/dist/test/test.html), nose 致力于提供比标准的unittest 模块更广泛的功能,同时保持与该模块的兼容性,py.test则采用了与unittest有些不同的方法,试图尽可能消除样板测试代码.这两个第三方模块都支持测试发现,所以呢没必要写一个总体的测试程序——因为模块将自己搜索测试程序.这使得测试整个代码树或某一部分 (比如那些已经起作用的模块)变得很容易.那些对测试严重关切的人,在决定使用哪个测试工具之前,对这两个(以及任何其他有吸引力的)第三方模块进行研究都是值 得的.

if __name__ =="__main__":

import doctest

doctest.testmod()

在程序内部使用doctest也是可能的.比如,blocks.py程序(其模块在后面)有自己函数的doctest,但以如下代码结尾:

if __name__== "__main__":

main()

另一种执行doctest的方法是使用unittest模块创建单独的测试程序.在概念上, unittest模块是根据Java的JUnit单元测试库进行建模的,并用于创建包含测试用例的测试套件.unittest模块可以基于doctests创建测试用例,而不需要知道程序或模块包含的任何事物——只要知道其包含doctest即可.所以呢,为给blocks.py程序制作一个测试套件,我们可以创建如下的简单程序(将其称为test_blocks.py):

import unittest

import blocks

suite = unittest.TestSuite()

suite.addTest(doctest.DocTestSuite(blocks))

runner = unittest.TextTestRunner()

print(runner.run(suite))

注意,如果釆用这种方法,程序的名称上会有一个隐含的约束:程序名必须是有效的模块名.所以呢,名为convert-incidents.py的程序的测试不能写成这样.因为import convert-incidents不是有效的,在Python标识符中,连接符是无效的(避开这一约束是可能的,但最简单的解决方案是使用总是有效模块名的程序文件名,比如,使用下划线替换连接符).这里展示的结构(创建一个测试套件,添加一个或多个测试用例或测试套件,运行总体的测试套件,输出结果)是典型的机遇unittest的测试.运行时,这一特定实例产生如下结果:

...

.............................................................................................................

OK

如果我们尝试将测试分离开(典型情况下是要测试的每个程序和模块都有一个测试用例),就不要再使用doctests,而是直接使用unittest模块的功能——尤其是我们习惯于使用JUnit方法进行测试时ounittest模块会将测试分离于代码——对大型项目(测试编写人员与开发人员可能不一致)而言,这种方法特别有用.此外,unittest单元测试编写为独立的Python模块,所以呢,不会像在docstring内部编写测试用例时受到兼容性和明智性的限制.

典型情况下,测试套件是通过创建unittest.TestCase的子类实现的,其中每个名称 以"test"开头的方法都是一个测试用例.如果我们需要完成任何创建操作,就可以在一个名为setUp()的方法中实现;类似地,对任何清理操作,也可以实现一个名为 tearDown()的方法.在测试内部,有大量可供我们使用的unittest.TestCase方法,包括 assertTrue()、assertEqual()、assertAlmostEqual()(对于测试浮点数很有用)、assertRaises() 以及更多,还包括很多对应的逆方法,比如assertFalse()、assertNotEqual()、failIfEqual()、 failUnlessEqual ()等.

结构上看,测试不同数据类型实质上是一样的,所以呢,我们将只为测试列表编写测试用例,而将其他的留作练习.test_Atomic.py模块必须导入unittest模块与要进行测试的Atomic模块.

创建unittest文件时,我们通常创建的是模块而非程序.在每个模块内部,我们定义一个或多个unittest.TestCase子类.比如,test_Atomic.py模块中仅一个单独的 unittest-TestCase子类,也就是TestAtomic (稍后将对其进行讲解),并以如下两行结束:

if name == "__main__":

unittest.main()

这两行使得该模块可以单独运行.当然,该模块也可以被导入并从其他测试程序中运行——如果这只是多个测试套件中的一个,这一点是有意义的.

如果想要从其他测试程序中运行test_Atomic.py模块,那么可以编写一个与此类似的程序.我们习惯于使用unittest模块执行doctests,比如:

import test_Atomic

suite = unittest.TestLoader().loadTestsFromTestCase(test_Atomic.TestAtomic)

pnnt(runner.run(suite))

这里,我们已经创建了一个单独的套件,这是通过让unittest模块读取test_Atomic 模块实现的,并且使用其每一个test*()方法(本实例中是test_list_success()、test_list_fail(),稍后很快就会看到)作为测试用例.

我们现在将查看TestAtomic类的实现.对通常的子类(不包括unittest.TestCase 子类),不怎么常见的是,没有必要实现初始化程序.在这一案例中,我们将需要建立 一个方法,但不需要清理方法,并且我们将实现两个测试用例.

def setUp(self):

self.original_list = list(range(10))

我们已经使用了 unittest.TestCase.setUp()方法来创建单独的测试数据片段.

def test_list_succeed(self):

items = self.original_list[:]

with Atomic.Atomic(items) as atomic:

self.assertEqual(items,

def test_list_fail(self):

with self.assertRaises(AttributeError):

atomic.poop() # Typo

self.assertListEqual(items, self.original_list)

性能剖析(Profiling)

如果程序运行很慢,或者消耗了比预期内要多得多的内存,那么问题通常是选择的算法或数据结构不合适,或者是以低效的方式进行实现.不管问题的原因是什么, 最好的方法都是准确地找到问题发生的地方,而不只是检査代码并试图对其进行优化. 随机优化会导致引入bug,或者对程序中本来对程序整体性能并没有实际影响的部分进行提速,而这并非解释器耗费大部分时间的地方.

在深入讨论profiling之前,注意一些易于学习和使用的Python程序设计习惯是有意义的,并且对提高程序性能不无裨益.这些技术都不是特定于某个Python版本的, 而是合理的Python程序设计风格.第一,在需要只读序列时,最好使用元组而非列表; 第二,使用生成器,而不是创建大的元组和列表并在其上进行迭代处理;第三,尽量使用Python内置的数据结构 dicts、lists、tuples 而不实现自己的自定义结构,因为内置的数据结构都是经过了高度优化的;第四,从小字符串中产生大字符串时, 不要对小字符串进行连接,而是在列表中累积,最后将字符串列表结合成为一个单独的字符串;第五,也是最后一点,如果某个对象(包括函数或方法)需要多次使用属性进行访问(比如访问模块中的某个函数),或从某个数据结构中进行访问,那么较好的做法是创建并使用一个局部变量来访问该对象,以便提供更快的访问速度.

Python标准库提供了两个特别有用的模块,可以辅助调査代码的性能问题.一个是timeit模块——该模块可用于对一小段Python代码进行计时,并可用于诸如对两个或多个特定函数或方法的性能进行比较等场合.另一个是cProfile模块,可用于profile 程序的性能——该模块对调用计数与次数进行了详细分解,以便发现性能瓶颈所在.

if __name__ == "__main__":

repeats = 1000

for function in ("function_a", "function_b", "function_c"):

t = timeit.Timer("{0}(X, Y)".format(function),"from __main__ import {0}, X, Y".format(function))

sec = t.timeit(repeats) / repeats

赋予timeit.Timer()构造子的第一个参数是我们想要执行并计时的代码,其形式是字符串.这里,该字符串是"function_a(X,Y)";第二个参数是可选的,还是一个待执行的字符串,这一次是在待计时的代码之前,以便提供一些建立工作.这里,我们从 __main__ (即this)模块导入了待测试的函数,还有两个作为输入数据传入的变量(X 与Y),这两个变量在该模块中是作为全局变量提供的.我们也可以很轻易地像从其他模块中导入数据一样来进行导入操作.

调用timeit.Timer对象的timeit()方法时,首先将执行构造子的第二个参数(如果有), 之后执行构造子的第一个参数并对其执行时间进行计时.timeit.Timer.timeit()方法的返回值是以秒计数的时间,类型是float.默认情况下,timeit()方法重复100万次,并返回所 有这些执行的总秒数,但在这一特定案例中,只需要1000次反复就可以给出有用的结果, 所以呢对重复计数次数进行了显式指定.在对每个函数进行计时后,使用重复次数对总数进行除法操作,就得到了平均执行时间,并在控制台中打印出函数名与执行时间.

在这一实例中,function_a()显然是最快的——至少对于这里使用的输入数据而言. 在有些情况下一一比如输入数据不同会对性能产生巨大影响——可能需要使用多组输入数据对每个函数进行测试,以便覆盖有代表性的测试用例,并对总执行时间或平均执行时间进行比较.

之后我们可以轻易地对其他两个函数进行计时,以便对其进行整体的比较.

cProfile.run("for i in ranged 1000): {0}(X, Y)".format(function))

我们必须将重复的次数放置在要传递给cProfile.run()函数的代码内部,但不需要做任何创建,因为模块函数会使用内省来寻找需要使用的函数与变量.这里没有使用显式的print()语句,因为默认情况下,cProfile.run()函数会在控制台中打印其输出.下面给出的是所有函数的相关结果(有些无关行被省略,格式也进行了稍许调整,以便与页面适应):

ncalls tottime percall cumtime percall filename:lineno(function)

①.000 0.001 0.000 0.001 0.000 {built-in method len}

ncalls ("调用的次数")列列出了对指定函数(在filename:lineno(function)中列出) 的调用次数.回想一下我们重复了 1000次调用,所以呢必须将这个次数记住.tottime ("总的时间")列列出了某个函数中耗费的总时间,但是排除了函数调用的其他函数内部花费的时间.第一个percall列列出了对函数的每次调用的平均时间(tottime // ncalls). cumtime ("累积时间")列出了在函数中耗费的时间,并且包含了函数调用的其他函数内部花费的时间.第二个percall列列出了对函数的每次调用的平均时间,包括其调用的函数耗费的时间.

在cProfile术语学中,原始调用指的就是非递归的函数调用.

下面给出的是一个非常短的控制台会话实例,为使其适合页面展示,进行了适当调整,我们自己的输入则以粗体展示:

Welcome to the profile statistics browser.

% read profile.dat

profile.dat% callers function_b

Random listing order was used

Function was called by...

ncalls tottime cumtime

profile.dat% callees function_b

Function called...

①.000 0.001 0.001 built-in method len

profile.dat% quit

输入help可以获取命令列表,help后面跟随命令名可以获取该命令的更多信息.比如, help stats将列出可以赋予stats命令的参数.还有其他一些可用的工具,可以提供profile数据的图形化展示形式,比如 RunSnakeRun (), 该工具需要依赖于wxPython GUI库.

使用timeit与cProfile模块,我们可以识别出我们自己代码中哪些区域会耗费超过预期的时间;使用cProfile模块,还可以准确算岀时间消耗在哪里.

python3和python2区别有什么

核心类差异

须使用绝对路径,否则只能使用相关导入的方式来进行导入.

必须用新式类应用多重继承.

以在缩进中可以同时允许 tab 和 space 在代码中共存.这种等价机制会导致部分 IDE 使用存在问题.

inconsistent use of tabs and spaces in indentation.

python学习网,免费的python学习网站,欢迎在线学习!

废弃类差异

了大数据集生成效率

map(),filter(),但是可以通过 list 强行转换:

①.0. 字典变量的 has_key 函数被 Python 废弃,统一使用 in 关键词

修改类差异

① 浮点数除法操作符"/"和"//"的区别

" / ":

浮点数;

"//":

① raise IOError, "file error" #抛出异常

① raise IOError("file error") #抛出异常

① i = 1

① 11 'test' #True

① 11 'test' # TypeError: unorderable types: int() str()

Python3和Python2的区别?

具体区别如下

python3与python2.7相比有什么变化,python3会成为主流吗

①性能?

以取得很好的优化结果.

中国 = 'china'

print(中国)

china

①.)去除了,全部改用!=

例如:

'0b110110110'

对象和seq是可迭代的.

class C(object):

? ? ? def __init__(self, a):

? ? ? ? ?print('C', a)

class D(C):

? ? ? def __init(self, a):

? ? ? ? ?super().__init__(a) # 无参数调用super()

class Foo(*bases, **kwds):

? pass

def foo(cls_a):

? ? ? def print_func(self):

? ? ? ? ?print('Hello, world!')

? ? ? cls_a.print = print_func

? ? ? return cls_a

@foo

C().print()

Hello, world!

b = b'china'

type(b)

type 'bytes'

str对象和bytes对象可以使用.encode() (str - bytes) or .decode() (bytes - str)方法相互转化.

s = b.decode()

s

'china'

b1 = s.encode()

b1

b'china'

dict.has_key(),用 in替代它吧

①.)引入抽象基类(Abstraact Base Classes,ABCs).

import collections

print('\n'.join(dir(collections)))

Callable

Container

Hashable

ItemsView

Iterable

Iterator

KeysView

Mapping

MappingView

MutableMapping

MutableSequence

MutableSet

NamedTuple

Sequence

Set

Sized

ValuesView

__all__

__builtins__

__doc__

__file__

__name__

_abcoll

_itemgetter

_sys

defaultdict

deque

①.)所以异常都从 BaseException继承,并删除了StardardError

try:

... ? ?raise NotImplementedError('Error')

... except NotImplementedError, error:

... ? ?print error.message

Error

? ? ? raise NotImplementedError('Error')

? ? except NotImplementedError as error: #注意这个 as

? ? ? print(str(error))

①.)移除了cPickle模块,可以使用pickle模块代替.最终我们将会有一个透明高效的模块.

rexec, sets, sha, stringold, strop, sunaudiodev, timing和xmllib模块

①.)xrange() 改名为range(),要想使用range()获得一个list,必须显式调用:

list(range(10))

\n\t\r \f')和b.split(b' ')来达到相同目的

()函数都被去除了

现在可以使用hasattr()来替换 callable(). hasattr()的语法如:hasattr(string, '__name__')

__delitem__调用

file

type 'file'

Traceback (most recent call last):

? ?file

NameError: name 'file' is not defined

python3--内置函数

python的常用内置函数

①abs() 函数返回数字的绝对值

dict()

{} ? ? ?#创建一个空字典类似于u={},字典的存取方式一般为key-value

help('math')查看math模块的用处

help(a)查看列表list帮助信息

dir(help)

['__call__', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']

a

①.0

next(it)

id(a)

a=["tom","marry","leblan"]

list(enumerate(a))

oct(10)

①.0. bin() 返回一个整数 int 或者长整数 long int 的二进制表示

bin(10)

'0b1010'

'0b1111'

①.1.eval() 函数用来执行一个字符串表达式,并返回表达式的值

f=open('test.txt')

bool()

False

bool(1)

True

bool(10)

bool(10.0)

isinstance(a,int)

isinstance(a,str)

class ? User(object):

? ? def__init__(self):

class Persons(User):

? ? ? ? ? super(Persons,self).__init__()

float(1)

①0

float(10)

①.0.0

iter(a)

for i in iter(a):

... ? ? ? ? print(i)

tuple(a)

s = "playbasketball"

len(s)

len(a)

class User(object):

? ?def __init__(self,name):

? ? ? ? ? ? self.name = name

? def get_name(self):

? ? ? ? ? ? return self.get_name

? @property

? ?def name(self):

? ? ? ? ? ?return self_name

list(b)

range(10)

range(0, 10)

class w(object):

a = w()

getattr(a,'s')

complex(1)

(1+0j)

complex("1")

max(b)

class Num(object):

...? ? a=1

.. print1 = Num()

print('a=',print1.a)

a= 1

print('b=',print1.b)

print('c=',print1.c)

delattr(Num,'b')

Traceback (most recent call last):? File "", line 1, inAttributeError: 'Num' object has no attribute 'b'

hash("tom")

a= set("tom")

b = set("marrt")

a,b

({'t', 'm', 'o'}, {'m', 't', 'a', 'r'})

ab#交集

{'t', 'm'}

a|b#并集

{'t', 'm', 'r', 'o', 'a'}

a-b#差集

{'o'}

以上就是土嘎嘎小编大虾米为大家整理的相关主题介绍,如果您觉得小编更新的文章只要能对粉丝们有用,就是我们最大的鼓励和动力,不要忘记讲本站分享给您身边的朋友哦!!

版权声明:倡导尊重与保护知识产权。未经许可,任何人不得复制、转载、或以其他方式使用本站《原创》内容,违者将追究其法律责任。本站文章内容,部分图片来源于网络,如有侵权,请联系我们修改或者删除处理。

编辑推荐

热门文章