Python的函数参数传递

  • 在Python中,strings,tuples=('abc',123,2.2,'join),numbers 是不可更改的对象。
  • list=['abc',123,2.23,'john'],dict等则是可以修改的对象。

示例:

  1. a = 1
  2. def fun(a):
  3. a = 2
  4. fun(a)
  5. print a #
  1. a = []
  2. def fun(a):
  3. a.append(1)
  4. fun(a)
  5. print a # [1]

@staticmethod和@classmethod

  • python有3个方法,即静态方法(staticmethod),类方法(classmethod)和实例方法。
  1. def foo(x):
  2. print "executing foo(%s)"%(x)
  3.  
  4. class A(object):
  5. def foo(self,x):
  6. print "executing foo(%s,%s)"%(self,x)
  7.  
  8. @classmethod
  9. def class_foo(cls,x):
  10. print "executing class_foo(%s,%s)"%(cls,x)
  11.  
  12. @staticmethod
  13. def static_foo(x):
  14. print "executing static_foo(%s)"%x
  15.  
  16. a=A()

这个self和cls是对类或者实例的绑定,对于一般的函数来说我们可以这么调用foo(x),这个函数就是最常用的,它的工作跟任何东西(类,实例)无关.对于实例方法,我们知道在类里每次定义方法的时候都需要绑定这个实例,就是foo(self, x),为什么要这么做呢?因为实例方法的调用离不开实例,我们需要把实例自己传给函数,调用的时候是这样的a.foo(x)(其实是foo(a, x)).类方法一样,只不过它传递的是类而不是实例,A.class_foo(x).注意这里的self和cls可以替换别的参数,但是python的约定是这俩,还是不要改的好.

对于静态方法其实和普通的方法一样,不需要对谁进行绑定,唯一的区别是调用的时候需要使用a.static_foo(x)或者A.static_foo(x)来调用.

类变量和实例变量???????

  1. class Person:
  2. name=[]
  3.  
  4. p1=Person()
  5. p2=Person()
  6. p1.name.append(1)
  7. print p1.name # [1]
  8. print p2.name # [1]
  9. print Person.name # [1]
  1. class Test(object):
  2. num_of_instance = 0
  3. def __init__(self, name):
  4. self.name = name
  5. Test.num_of_instance += 1
  6.  
  7. if __name__ == '__main__':
  8. print Test.num_of_instance
  9. t1 = Test('jack')
  10. print Test.num_of_instance
  11. t2 = Test('lucy')
  12. print t1.name , t1.num_of_instance
  13. print t2.name , t2.num_of_instance

Python自省

  • 自省(让对象告诉我们他是什么),用于实现在运行时获取未知对象的信息。

访问对象属性:

  • hasattr(obj, attr)    这个方法用于检查obj是否有一个名为attr的值的属性,返回一个布尔值。
  • getattr(obj, attr)    调用这个方法将返回obj中名为attr值的属性的值,例如如果attr为’bar’,则返回obj.bar。
  • setattr(obj, attr, val)  调用这个方法将返回obj中名为attr值的属性的值,例如如果attr为’bar’,则返回obj.bar。

推导式

  • 列表推导式(list) 提供一种方便的列表创建方法,返回一个列表。格式:用中括号括起来,中间用for语句,后面跟if语句用作判读,满足条件的传到for语句前面用作构建先的列表.
  1. >>> li=[i*2 for i in range(10) if i % 2 == 0]
  2. >>> print (li)
  3. [0, 4, 8, 12, 16]
  4. >>>
  • 字典推导式(dic) 格式:d = {key: value for (key, value) in iterable}
  1. >>> mca={"a":1, "b":2, "c":3, "d":4}
  2. >>> dicts={v:k for k,v in mca.items()}
  3. >>> print (dicts)
  4. {1: 'a', 2: 'b', 3: 'c', 4: 'd'}
  5. >>>
  • 集合推导式(跟列表推导式的区别:1.不使用中括号,使用大括号;2.结果中无重复;3.结果是一个set()集合,集合里面是一个序列)
  1. >>> squared={i*2 for i in [1,1,2]}
  2. >>> print (squared)
  3. set([2, 4])
  4. >>>

Python中单下划线和双下划线??????

_foo:

  • 在一个模块中以单下划线开头的变量和函数被默认当作内部函数,如果使用 from a_module import * 导入时,这部分变量和函数不会被导入。不过值得注意的是,如果使用 import a_module 这样导入模块,仍然可以用 a_module._some_var 这样的形式访问到这样的对象。
  • 一种约定,用来指定变量私有.程序员用来指定私有变量的一种方式.

__foo:

  • 这个有真正的意义:解析器用_classname__foo来代替这个名字,以区别和其他类相同的命名.
  • 双下划线开头的命名形式在 Python 的类成员中使用表示名字改编 (Name Mangling),即如果有一 Test 类里有一成员 __x,那么 dir(Test) 时会看到 _Test__x 而非 __x。这是为了避免该成员的名称与子类中的名称冲突。但要注意这要求该名称末尾没有下划线.

__foo__:

  • 一种约定,Python内部的名字,用来区别其他用户自定义的命名,以防冲突.
  • 双下划线开头双下划线结尾的是一些 Python 的“魔术”对象,如类成员的 __init__、__del__、__add__、__getitem__ 等,以及全局的 __file__、__name__ 等。 Python 官方推荐永远不要将这样的命名方式应用于自己的变量或函数,而是按照文档说明来使用。
  1. >>> class MyClass():
  2. ... def __init__(self):
  3. ... self.__superprivate = "Hello"
  4. ... self._semiprivate = ", world!"
  5. ...
  6. >>> mc = MyClass()
  7. >>> print mc.__superprivate
  8. Traceback (most recent call last):
  9. File "<stdin>", line 1, in <module>
  10. AttributeError: myClass instance has no attribute '__superprivate'
  11. >>> print mc._semiprivate
  12. , world!
  13. >>> print mc.__dict__
  14. {'_MyClass__superprivate': 'Hello', '_semiprivate': ', world!'}

字符串格式化:%和.format

对于%最烦人的是它无法同时传递一个变量和元组.

  1. name = (1,2,3)
  2. print ("hi there %s" % name) # 报错
  3. print ("hi there %s" % (name,)) # 提供一个单元素的数组而不是一个参数

.format通过{}和.来代替%

  • 通过位置:
  1. print ("{0},{1}".format('lujf',123))
  • 通过关键字参数
  1. print ("{name},{age}".format(name='lujf',age=23))
  • 通过对象属性???????
  1. class Person:
  2. def __init__(self,name,age):
  3. self.name,self.age = name,age
  4. def __str__(self):
  5. return 'This guy is {self.name},is {self.age} old'.format(self=self)
  • 通过下标
  1. p = ['lujf',23]
  2. print ('{0[0]},{0[1]}'.format(p))

迭代器和生成器

迭代器:

  • 迭代器是访问集合元素的一种方式。迭代器对象从集合的第一个元素开始访问,知道所有的元素被访问完结束。迭代器只能往前不会后退。
  • 对于原生支持随机访问的数据结构(如tuple、list),迭代器和经典for循环的索引访问相比并无优势,反而丢失了索引值(可以使用内建函数enumerate()找回这个索引值)。但对于无法随机访问的数据结构(比如set)而言,迭代器是唯一的访问元素的方式。
  • 迭代器的一大优点是不要求事先准备好整个迭代过程中所有的元素。迭代器仅仅在迭代到某个元素时才计算该元素,而在这之前或之后,元素可以不存在或者被销毁。这个特点使得它特别适合用于遍历一些巨大的或是无限的集合,比如几个G的文件,或是斐波那契数列等等
  • 迭代器更大的功劳是提供了一个统一的访问集合的接口,只要定义了__iter__()方法对象,就可以使用迭代器访问。

    迭代器有两个基本的方法

    • next方法:返回迭代器的下一个元素
    • __iter__方法:返回迭代器对象本身
  1. class Fab(object):
  2. def __init__(self, max):
  3. self.max = max
  4. self.n, self.a, self.b = 0, 0, 1
  5.  
  6. def __iter__(self):
  7. return self
  8.  
  9. def next(self):
  10. if self.n < self.max:
  11. r = self.b
  12. self.a, self.b = self.b, self.a + self.b
  13. self.n = self.n + 1
  14. return r
  15. raise StopIteration() #python处理迭代器越界是抛出StopIteration异常

使用迭代器:

  • 使用内建的工厂函数iter(iterable)可以获取迭代器对象:
  1. >>> lst = range(5)
  2. >>> it = iter(lst)
  3. >>> it
  4. <listiterator object at 0x01A63110>
  • 使用next()方法可以访问下一个元素:
  1. >>> it.next()
  2. 0
  3. >>> it.next()
  4. 1
  5. >>> it.next()
  6. 2

事实上,因为迭代器如此普遍,python专门为for关键字做了迭代器的语法糖。在for循环中,Python将自动调用工厂函数iter()获得迭代器,自动调用next()获取元素,还完成了检查StopIteration异常的工作。

生成器:

  • 带有 yield 的函数在 Python 中被称之为 generator(生成器)。
  1. def fab(max):
  2. n, a, b = 0, 0, 1
  3. while n < max:
  4. yield b
  5. a, b = b, a + b
  6. n = n + 1

简单地讲,yield 的作用就是把一个函数变成一个 generator,带有 yield 的函数不再是一个普通函数,Python 解释器会将其视为一个 generator,调用 fab(5) 不会执行 fab 函数,而是返回一个 iterable 对象!在 for 循环执行时,每次循环都会执行 fab 函数内部的代码,执行到 yield b 时,fab 函数就返回一个迭代值,下次迭代时,代码从 yield b 的下一条语句继续执行,而函数的本地变量看起来和上次中断执行前是完全一样的,于是函数继续执行,直到再次遇到 yield。看起来就好像一个函数在正常执行的过程中被 yield 中断了数次,每次中断都会通过 yield 返回当前的迭代值。

  • return的作用

在一个生成器中,如果没有return,则默认执行到函数完毕;如果遇到return,如果在执行过程中 return,则直接抛出 StopIteration 终止迭代。

*args and **kwargs

如果我们不确定往一个函数中传入多少参数,或者我们希望以元组(tuple)或者列表(list)的形式传参数的时候,我们可以使用*args 。当函数的参数前面有一个星号*号的时候表示这是一个可变的位置参数。星号*把序列或者集合解包(unpack)成位置参数。

  1. def print_everything(*args):
  2. for count, thing in enumerate(args): #enumerate()为python内置函数
  3. print('{},{}'.format(count, thing))
  4. print_everything('apple', 'banana', 'cabbage')
  5.  
  6. #输出
  7. #0,apple
  8. #1,banana
  9. #2,cabbage

如果我们不知道往函数中传递多少个关键词参数或者想传入字典的值作为关键词参数的时候我们可以使用**kwargs。两个星号**把字典解包成关键词参数。

  1. def table_things(**kwargs):
  2. for name, value in kwargs.items(): #Python 字典(Dictionary) items()方法
  3. print ('{} = {}'.format(name, value))
  4. table_things(apple = 'fruit', cabbage = 'vegetable')
  5.  
  6. #输出
  7. #apple = fruit
  8. #cabbage = vegetable

面向切面编程AOP和装饰器

  1. # -*- coding: utf-8 -*-
  2. import time
  3.  
  4. def foo():
  5. print
  6. 'in foo()'
  7.  
  8. # 定义一个计时器,传入一个,并返回另一个附加了计时功能的方法
  9. def timeit(func):
  10. # 定义一个内嵌的包装函数,给传入的函数加上计时功能的包装
  11. def wrapper():
  12. start = time.clock()
  13. func()
  14. end = time.clock()
  15. print ('used:', end - start)
  16.  
  17. # 将包装后的函数返回
  18. return wrapper
  19.  
  20. foo = timeit(foo)
  21. foo()

在在这个例子中,函数进入和退出时需要计 时,这被称为一个横切面(Aspect),这种编程方式被称为面向切面的编程(Aspect-Oriented Programming)。

Python重载(python 自然就不需要函数重载)

函数重载主要是为了解决两个问题:

  • 可变参数类型(因为 python 可以接受任何类型的参数,如果函数的功能相同,那么不同的参数类型在 python 中很可能是相同的代码,没有必要做成两个不同函数。)
  • 可变参数个数(缺省参数)

示例:

  1. def f(a,L=[]):
  2. L.append(a)
  3. print L
  1. f(1) #[1]
    f(2) #[1,2]

缺省参数在python中是与函数绑定在一起的。

也就是说,一个函数中定义了一个缺省参数,那么这个参数会随着被调用而改变。(一个坑)

在一次调用中改变了缺省参数的值,可能会影响到这个函数的另外一次调用。

__new__ 和__init__的区别

  1. lass Book(object):
  2. def __new__(cls, title):
  3. print'__new__'
  4. return super(Book, cls).__new__(cls)
  5.  
  6. def __init__(self, title):
  7. print'__init__'
  8. super(Book, self).__init__(self)
  9. self.title = title
  10.  
  11. b = Book('The Django Book')
  12. print(b.title)

官方文档:

  • __init__是当实例对象创建完成后被调用的,然后设置对象属性的一些初始值。
  • __new__是在实例创建之前被调用的,因为它的任务就是创建实例然后返回该实例,是个静态方法

也就是,__new__在__init__之前被调用,__new__的返回值(实例)将传递给__init__方法的第一个参数,然后__init__给这个实例设置一些参数。

Python中的作用域

  • Python 中,一个变量的作用域总是由在代码中被赋值的地方所决定的。
  • 当 Python 遇到一个变量的话他会按照这样的顺序进行搜索:本地作用域(Local)→当前作用域被嵌入的本地作用域(Enclosing locals)→全局/模块作用域(Global)→内置作用域(Built-in)

GIL线程全局锁

  • 线程全局锁(Global Interpreter Lock),即Python为了保证线程安全而采取的独立线程运行的限制,说白了就是一个核只能在同一时间运行一个线程.

协程

简单点说协程是进程和线程的升级版,进程和线程都面临着内核态和用户态的切换问题而耗费许多切换时间,而协程就是用户自己控制切换的时机,不再需要陷入系统的内核态.

lambda函数

  • 简单来说,编程中提到的 lambda 表达式,通常是在需要一个函数,但是又不想费神去命名一个函数的场合下使用,也就是指匿名函数。
  1. map( lambda x: x*x, [y for y in range(10)] )
  1. def sq(x):
  2. return x * x
  3.  
  4. map(sq, [y for y in range(10)])
  • map()函数接收两个参数,一个是函数,一个是序列,map将传入的函数依次作用到序列的每个元素,并把结果作为新的list返回。

Python 引用和copy(),deepcopy()的区别

Python中对象之间的赋值是按引用传递的,如果要拷贝对象需要使用标准模板中的copy

  • 赋值:Python中对象之间的赋值是按引用传递的
  • copy.copy:浅拷贝,只拷贝父对象,不拷贝父对象的子对象。
  • copy.deepcopy:深拷贝,拷贝父对象和子对象。
  1. import copy
  2. a = [1, 2, 3, 4, ['a', 'b']] #原始对象
  3.  
  4. b = a #赋值,传对象的引用
  5. c = copy.copy(a) #对象拷贝,浅拷贝
  6. d = copy.deepcopy(a) #对象拷贝,深拷贝
  7.  
  8. a.append(5) #修改对象a
  9. a[4].append('c') #修改对象a中的['a', 'b']数组对象
  10.  
  11. print ('a = ', a)
  12. print ('b = ', b)
  13. print ('c = ', c)
  14. print ('d = ', d)
  15.  
  16. 输出结果:
  17. a = [1, 2, 3, 4, ['a', 'b', 'c'], 5]
  18. b = [1, 2, 3, 4, ['a', 'b', 'c'], 5]
  19. c = [1, 2, 3, 4, ['a', 'b', 'c']]
  20. d = [1, 2, 3, 4, ['a', 'b']]

注意: 浅拷贝和深拷贝的不同仅仅是对组合对象来说,所谓的组合对象就是包含了其它对象的对象,如列表,类实例。而对于数字、字符串以及其它“原子”类型,没有拷贝一说,产生的都是原对象的引用。

Python 的 is 和 ==

python中的对象包含三要素:id、type、value

其中 id 用来唯一标识一个对象。

  • is是对比地址
  • ==是对比值

read,readline 和 readlines

  • read 读取整个文件。
  • readline 读取下一行,使用生成器方法。
  • readlines 读取整个文件到一个迭代器以供我们遍历。
  1. f = open('poem.txt','r')
  2. a = f.read()
  3. print (a)
  1. f = open('poem.txt','r')
  2. result = list()
  3. for line in open('poem.txt'):
  4. line = f.readline()
  5. print (line)
  6. result.append(line)
  7. print (result)
  8. f.close()
  1. f = open('poem.txt', 'r') #以读方式打开文件
  2. result = list()
  3. for line in f.readlines(): #依次读取每行
  4. line = line.strip() #去掉每行头尾空白
  5. if not len(line) or line.startswith('#'): #判断是否是空行或注释行
  6. continue #是的话,跳过不处理
  7. result.append(line) #保存
  8. result.sort() #排序结果
  9. print result

Python的垃圾回收机制 (garbage collection)

Python中的垃圾回收是以引用计数为主,标记-清除分代收集为辅。

  • 引用计数:Python在内存中存储每个对象的引用计数,如果计数变成0,该对象就会消失,分配给该对象的内存就会释放出来。
  • 标记-清除:一些容器对象,比如list、dict、tuple,instance等可能会出现引用循环,对于这些循环,垃圾回收器会定时回收这些循环(对象之间通过引用(指针)连在一起,构成一个有向图,对象构成这个有向图的节点,而引用关系构成这个有向图的边)。
  • 分代收集:Python把内存根据对象存活时间划分为三代,对象创建之后,垃圾回收器会分配它们所属的代。每个对象都会被分配一个代,而被分配更年轻的代是被优先处理的,因此越晚创建的对象越容易被回收。

说明os,sys模块的不同

os模块负责程序与操作系统的交互,提供了访问操作系统底层的接口。

sys模块负责程序与Python解释器的交互,提供了一系列的函数和变量用户操作Python运行时的环境。

lambda表达式

简单来说,lambda表达式通常是当你需要使用一个函数,但是又不想费脑袋去命名一个函数的时候使用,也就是通常所说的匿名函数。

  1. #示例
  2. f = lambda x,y,z: x + y + z
  3. print(f(1,2,3))
  4. L = {'f1':(lambda x,y: x**2 + y**2),
  5. 'f2':(lambda x,y: x**3 + y**3),
  6. 'f3':(lambda x,y: x**4 + y**3)}
  7. print(L['f2'](3,2))

Python 面试题学习的更多相关文章

  1. Python面试题整理-更新中

    几个链接: 编程零基础应当如何开始学习 Python ? - 路人甲的回答 网易云课堂上有哪些值得推荐的 Python 教程? - 路人甲的回答 怎么用最短时间高效而踏实地学习 Python? - 路 ...

  2. 震惊!几道Python 理论面试题,Python面试题No18

    本面试题题库,由公号:非本科程序员 整理发布 第1题: 简述解释型和编译型编程语言? 解释型语言编写的程序不需要编译,在执行的时候,专门有一个解释器能够将VB语言翻译成机器语言,每个语句都是执行的时候 ...

  3. 面试前赶紧看了5道Python Web面试题,Python面试题No17

    目录 本面试题题库,由公号:非本科程序员 整理发布 第1题: Flask中的请求上下文和应用上下文是什么? 第2题:django中间件的使用? 第3题: django开发中数据做过什么优化? 第4题: ...

  4. 千万不要错过这几道Python面试题,Python面试题No16

    第1题: python下多线程的限制以及多进程中传递参数的方式? python多线程有个全局解释器锁(global interpreter lock),简称GIL,这个GIL并不是python的特性, ...

  5. Python 装饰器学习

    Python装饰器学习(九步入门)   这是在Python学习小组上介绍的内容,现学现卖.多练习是好的学习方式. 第一步:最简单的函数,准备附加额外功能 1 2 3 4 5 6 7 8 # -*- c ...

  6. Python面试题 —— 获取列表中位数

    中位数是一个可将数值集合划分为相等的上下两部分的一个数值.如果列表数据的个数是奇数,则列表中间那个数据就是列表数据的中位数:如果列表数据的个数是偶数,则列表中间那2个数据的算术平均值就是列表数据的中位 ...

  7. 【Todo】Python面试题分析记录(修饰器等)

    首先,看这一段代码: class A(object): x = 1 gen = (lambda t: (t for _ in xrange(10)))(x) if __name__ == '__mai ...

  8. Requests:Python HTTP Module学习笔记(一)(转)

    Requests:Python HTTP Module学习笔记(一) 在学习用python写爬虫的时候用到了Requests这个Http网络库,这个库简单好用并且功能强大,完全可以代替python的标 ...

  9. 从Theano到Lasagne:基于Python的深度学习的框架和库

    从Theano到Lasagne:基于Python的深度学习的框架和库 摘要:最近,深度神经网络以“Deep Dreams”形式在网站中如雨后春笋般出现,或是像谷歌研究原创论文中描述的那样:Incept ...

随机推荐

  1. ElasticStack系列之七 & IK自动热更新原理与实现

    一.热更新原理 elasticsearch开启加载外部词典功功能后,会每60s间隔进行刷新字典.具体原理代码如下所示: public void loadDic(HttpServletRequest r ...

  2. Digia公司投资qt

    sklearn实战-乳腺癌细胞数据挖掘(博主亲自录制视频) https://study.163.com/course/introduction.htm?courseId=1005269003& ...

  3. Hadoop生态圈-phoenix的视图(view)管理

    Hadoop生态圈-phoenix的视图(view)管理 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.

  4. 第10章-Vue.js 项目实战

    一.本节内容 掌握项目环境中路由的配置方法 ***** 熟练掌握编写单文件组件的编写 *** 能够使用swiper.js进行轮播图组件的封装 能够使用axios进行数据请求 二.webpack项目的目 ...

  5. 《剑指offer》 面试题43 n个骰子的点数 (java)

    引言:写这篇文章的初衷只是想做个笔记,因为这道题代码量有点大,有点抽象,而书上并没有详细的注释.为了加深印象和便于下次复习,做个记录. 原题:把n个骰子扔到地上,所有骰子朝上一面的点数之后为s. 输入 ...

  6. bzoj千题计划148:bzoj1537: [POI2005]Aut- The Bus

    http://www.lydsy.com/JudgeOnline/problem.php?id=1537 朴素的转移:dp[i][j]=max(dp[i][j-1],dp[i-1][j])+p[i][ ...

  7. opencv产生随机的颜色

    //将HSV颜色空间值转换成RGB值,参考这里cv::Scalar HSV2RGB(const float h, const float s, const float v) { ); - h_i; - ...

  8. 【leetcode 简单】 第九十三题 二进制手表

    二进制手表顶部有 4 个 LED 代表小时(0-11),底部的 6 个 LED 代表分钟(0-59). 每个 LED 代表一个 0 或 1,最低位在右侧. 例如,上面的二进制手表读取 “3:25”. ...

  9. jquery ajax complete 方法

    jquery ajax var ajaxTimeoutTest = $.ajax({ url:'',  //请求的URL timeout : 1000, //超时时间设置,单位毫秒 type : 'g ...

  10. 字典树&&01字典树专题&&对字典树的理解

    对于字典树和01字典树的一点理解: 首先,字典树建树的过程就是按照每个数的前缀来的,如果你要存储一个全小写字母字符串,那么这个树每一个节点最多26个节点,这样的话,如果要找特定的单词的话,按照建树的方 ...