一.Python 中类方法、类实例方法、静态方法有何区别
定义区别:
1.类方法和静态方法分别有专门的修饰符 @classmethod,@staticmethod。
2.实例方法有self参数,类方法有cls参数(类参数),静态方法是不需要这些附加参数的
3.静态方法实际上跟该类没有太大关系
访问区别:
- 类和实例都可以访问静态方法和类方法
- 从理论上来说,类是不能访问实例方法的,但是可以把实例/类作为参数传入,访问如下:
a=Myclass()
Myclass.method(a)
Myclass.method(Myclass)
二.Python 中如何动态获取和设置对象的属性
hasattr,setattr,getattr
三.Python 的内存管理机制及调优手段
点这里[https://www.jianshu.com/p/6e82c7a54c33]
内存泄漏:有 del() 函数的对象间的循环引用是导致内存泄漏的主凶。
不使用一个对象时使用:del object 来删除一个对象的引用计数就可以有效防止内存泄漏问题。
通过 Python 扩展模块 gc 来查看不能回收的对象的详细信息。
可以通过 sys.getrefcount(obj) 来获取对象的引用计数,并根据返回值是否为 0 来判断是否内存泄漏。
四.函数
- 函数参数
Python 的参数传递有:位置参数、默认参数、可变参数、关键字参数
函数的传值到底是值传递还是引用传递,要分情况:
不可变参数 用值传递
可变参数 引用传递
有这样一段代码,print c 会输出什么:
a = 10
b = 20
c = [a]
a = 15
print c
>>>[10]
像列表,字典这样的对象是通过引用传递、和 C 语言里面的用指针传递数组很相似,可变对象
能在函数内部改变。
对缺省参数的理解
缺省参数指在调用函数的时候没有传入参数的情况下,调用默认的参数,在调用函数的同时赋值时,所传入的参数会替代默认参数。
*args 是不定长参数,他可以表示输入参数是不确定的,可以是任意多个。元组方式传入
**kwargs 是关键字参数,赋值的时候是以键 = 值的方式,参数是可以任意多对在定义函数的时候不确定会有多少参数会传入时,就可以使用两个参数。字典式传入
- 为什么函数名字可以当做参数用
Python 中一切皆对象,函数名是函数在内存中的空间,也是一个对象。
4.递归函数终止的条件
递归的终止条件一般定义在递归函数内部,在递归调用前要做一个条件判断,根据判断的结果选择是继续调用自身,还是 return;返回终止递归。
终止的条件:
. 判断递归的次数是否达到某一限定值
. 判断运算的结果是否达到某个范围等,根据设计的目的来选择
5.回调函数,如何通信的:
回调函数是把函数的指针(地址)作为参数传递给另一个函数,将整个函数当作一个对象,赋值给调用的函数。
- Python 主要的内置数据类型都有哪些? print dir( ‘a ’) 的输出
内建类型:布尔类型、数字、字符串、列表、元组、字典、集合;
输出字符串‘a’的内建方法;
- 一句话解决阶乘函数
reduce(lambda x,y: x*y, range(1,n+1))
8.lambda函数
lambda 函数是一个可以接收任意多个参数(包括可选参数)并且返回单个表达式值的函数
.lambda 函数比较轻便,很适合需要完成一项功能,但是此功能只在此一处使用,不用def给函数起名。
.匿名函数,一般用来给 filter, map 这样的函数式编程服务;
.作为回调函数,传递给某些应用
这段代码的输出结果将是什么:
>>> def multipliers():
... return [lambda x : i * x for i in range(4)]
...
>>> print [m(2) for m in multipliers()]
[6, 6, 6, 6] (不是我们想的[0, 2, 4, 6])
原因:
Python 闭包的延迟绑定。这意味着内部函数被调用时,参数的值在闭包内进行查找。
i的变量引用,等待4次循环结束后,i指向一个值i=3,这个时候,匿名函数才开始引用i=3
解决方法:
一种解决方法就是用 Python 生成器。
def multipliers():
for i in range(4): yield lambda x : i * x
另外一个解决方案就是添加默认参数,立即绑定。
def multipliers():
return [lambda x,a=i : a* x for i in range(4)]
第二种方法:添加了一个a=i,python函数中的默认参数,是在python 解释器遇到def(i=i)或lambda 关键字时,就必须初始化默认参数,此时for i in range(4),每循环一次,匿名函数的默认参数i,就需要找一次i的引用,i=0时,第一个匿名函数的默认参数值就是0,i=1时,第二个匿名函数的默认参数值就是1...
可以理解为:
def multipliers():
return [lambda x,i=0: ix, lambda x,i=1: ix, lambda x,i=2: ix, lambda x,i=3:ix i=3]
五.设计模式
1)单例模式
是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场。
相关链接
实现单例模式的几种方式:
.使用模块:
Python 的模块就是天然的单例模式,因为模块在第一次导入时,会生成 .pyc 文件,当第二次导入时,就会直接加载 .pyc 文件,而不会再次执行模块代码。因此,我们只需把相关的函数和数据定义在一个模块中,就可以获得一个单例对象
然后再从其他模块导入这个单例对象
.使用装饰器
def Singleton(cls):
_instance = {}
def _singleton(*args, **kargs):
if cls not in _instance:
_instance[cls] = cls(*args, **kargs)
return _instance[cls]
return _singleton
@Singleton
class A(object):
a = 1
def __init__(self, x=0):
self.x = x
a1 = A(2)
a2 = A(3)
a1,a2都是同一个实例
.使用类,但是多线程时会出问题,需要加锁
.基于new方法实现
当我们实例化一个对象时,是先执行了类的new方法(默认调用object.new),实例化对象;然后再执行类的init方法,对这个对象进行初始化,
class A(object):
_instance =None
def __new__(cls,*args,**kwargs):
if cls._instance = None:
cls._instance = object.__new__(cls)
return cls._instance
else:
return cls._instance
应用场景:
(1)资源共享的情况下,避免由于资源操作时导致的性能或损耗等。如日志文件,应用配置。
(2)控制资源的情况下,方便资源之间的互相通信。如线程池等。 1.网站的计数器 2.应用配置 3.多线程池 4.数据库配置,数据库连接池 5.应用程序的日志应用....
2).工厂模式
链接
当程序运行输入一个“类型”的时候,需要创建于此相应的对象。这就用到了工厂模式。在如此情形中,实现代码基于工厂模式,可以达到可扩展,可维护的代码。当增加一个新的类型,不在需要修改已存在的类,只增加能够产生新类型的子类。
简短的说,当以下情形可以使用工厂模式:
1.不知道用户想要创建什么样的对象
2.当你想要创建一个可扩展的关联在创建类与支持创建对象的类之间。
3)装饰器
本质上是一个 Python 函数,它可以在让其他函数在不需要做任何代码的变动的前提下增加额外的功能。装饰器的返回值也是一个函数的对象.
- 生成器
生成器、迭代器的区别:
生成器能做到迭代器能做的所有事,而使用生成器表达式取代列表解析可以同时节省内存。使用yield变成generator
>>> X = (i for i in range(10))
>>> print type(X)
<type 'generator'>
用“一行代码”实现将 1-N 的整数列表以 3 为单位分组,比如 1-100
分组后为:
print([[x for x in range(1,100)][i:i+3] for i in range(0,len(list_a),3)])
- 面向对象
类和对象
- Python 中 is 和==的区别:
is 判断的是 a 对象是否就是 b 对象,是通过 id 来判断的。
==判断的是 a 对象的值是否和 b 对象的值相等,是通过 value 来判断的。
2.python 魔法方法
魔法方法就是可以给你的类增加魔力的特殊方法,如果你的对象实现 (重载)了这些方法中的某一个,那么这个方法就会在特殊的情况下被 Python 所调用,如init,new,call,等等
3.面向对象中怎么实现只读属性
使用@property,将以访问属性的方式访问方法
>>> class Person(object):
... _age =38
... @property
... def age(self):
... return self._age
...
>>> p = Person()
>>> print p.age
38
>>> p.age = 12
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: can't set attribute
>>>
4.谈谈你对面向对象的理解?
面向对象是相对于面向过程而言的。面向过程语言是一种基于功能分析的、以算法为中心的程序设计方法;而面
向对象是一种基于结构分析的、以数据为中心的程序设计思想。在面向对象语言中有一个有很重要东西,叫做类。
面向对象有三大特性:封装、继承、多态。
6)正则表达式
.match 与 search 的区别:
match()函数只检测 RE 是不是在 string 的开始位置匹配,
search()会扫描整个 string 查找匹配;
.字符串查找和替换:
re.findall(r’目的字符串’,’原有字符串’) #查询
re.findall(r'cast','itcast.cn')[0]
re.sub(r‘要替换原字符’,’要替换新字符’,’原始字符串’)
re.sub(r'cast','heima','itcast.cn')