- Python的两个魔法方法:
__repr__
和__str__
- 实例:当同时定义了
__repr__
和__str__
方法时,print()方法会调用__str__
方法。 - 关系:
__str__
方法其实调用了__repr__
方法 - 使用:
__repr__
目的是为了表示清楚,是为开发者准备的。__str__
目的是可读性好,是为使用者准备的。
class Person(object):
def __init__(self,name):
self.name = name
def __repr__(self):
return self.name + "__repr__"
def __str__(self):
return self.name + "__str__"
wk=Person('wk')
print(wk)
- 匿名函数的使用
在map、filter、reduce方法中使用匿名函数lambda
map(lambda x : x**2,[1,2,3])
filter(lambda x: x >1 ,[1,2,3])
- 双端队列:collections中的deque
deque定义一个固定大小的队列,当队列插满时,会把多出来的元素移除队列,之所以叫双端队列,时因为它支持append和appendleft两个方法分别实现从右侧插入和左侧插入
from collections import deque
dq = deque([],3)
dq.append(1)
print(dq)
dq.append(2)
print(dq)
dq.append(3)
print(dq)
dq.append(4)
print(dq)
dq.appendleft(5) # 从左侧插入
print(dq)
# 输出结果
# deque([1], maxlen=3)
# deque([1, 2], maxlen=3)
# deque([1, 2, 3], maxlen=3)
# deque([2, 3, 4], maxlen=3)
# deque([5, 2, 3], maxlen=3)
- 标准库copy中的copy与deepcopy
import copy
a = [1,2,3,['a','b','c']]
b = copy.copy(a)
c = copy.deepcopy(a)
a[3].append(4)
print(id(a))
print(id(b))
print(id(c))
# 深浅拷贝都会新开辟地址
# 1899078673288
# 1899078323016
# 1899078638472
print(a)
print(b)
print(c)
# 但是不会为数组中的数组再开辟地址
# [1, 2, 3, ['a', 'b', 'c', 4]]
# [1, 2, 3, ['a', 'b', 'c', 4]]
# [1, 2, 3, ['a', 'b', 'c']]
print(id(a[3]))
print(id(b[3]))
print(id(c[3]))
# 1899078930184
# 1899078930184
# 1899078638664
- 标准库re正则表达式match和search的区别
re.match是从字符串首字母处匹配
re.search是遍历整个字符串匹配
re.findall遍历整个字符串,查找到所有符合要求的子串,组合成一个列表
import re
str = 'abc123xyz123x'
m = re.match("abc", str) # abc
m2 = re.search('123', str) # 123
m3 = re.match('123', str) # None
print(m.group())
print(m2.group())
# print(m3) 会报错
m4 = re.findall('123x', str) # ['123x', '123x']
print(m4)
- CPython的内存管理机制
变量的存储有三个区域,事先分配的静态内存、事先分配的可重复利用内存以及需要通过malloc和free来控制的自由内存。
python的内存在底层也是由malloc和free的方式来分配和释放,只是它代替程序员决定什么时候分配什么时候释放,同时也提供接口让用户手动释放,因此它有自己的一套内存管理体系,主要通过两种机制来实现,一个是引用计数,一个是垃圾回收。前者负责确定当前变量是否需要释放,后者解决前者解决不了的循环引用问题以及提供手动释放的接口del。
- 连接字符用join还是+
join的性能好于+,原因在于:字符串是不可变对象,当用操作符+连接字符串的时候,每执行一次+都会申请一块新的内存,热庵后复制上一个+操作的结果和本次操作的右操作符到这块内存空间,因此用+连接字符串的时候会涉及好几次内存申请和复制。而join在连接字符的时候,会先计算需要多大的内存存放结果,然后一次性申请所需内存并将字符串复制过去。 - 理解
__new__
和__init__
的区别
__init__
:初始化函数
__new__
:构造函数:用于创建对象并返回对象,当返回对象时会自动调用__init__方法进行初始化。
__init__
是实例方法,__new__
是静态方法 - with与上下文管理器
一个实现了__enter__
和__exit__
方法的对象就称之为上下文管理器。
__enter__()
- 进入上下文管理器的运行时上下文,在语句体执行前调用。如果有as子句,with语句将该方法的返回值赋值给 as 子句中的 target。
__exit__(exception_type, exception_value, traceback)
- 退出与上下文管理器相关的运行时上下文,返回一个布尔值表示是否对发生的异常进行处理。如果with语句体中没有异常发生,则__exit__
的3个参数都为None,即调用 __exit__(None, None, None)
,并且__exit__
的返回值直接被忽略。如果有发生异常,则使用 sys.exc_info 得到的异常信息为参数调用__exit__(exception_type, exception_value, traceback)
。出现异常时,如果__exit__(exception_type, exception_value, traceback)
返回 False,则会重新抛出异常,让with之外的语句逻辑来处理异常;如果返回 True,则忽略异常,不再对异常进行处理。
-
Xrange和range的区别是什么?
Xrange用于返回一个xrange对象,而range用于返回一个数组。不管那个范围多大,Xrange都使用同样的内存。 -
__call__
方法:
__call__()
是一种magic method,在类中实现这一方法可以使改类的实例(对象)像函数一样被调用。
默认情况下该方法在类中是没有被实现的。使用callable()方法可以判断某对象是否可以被调用。 -
元类
关键字:__metaclass__
元类的功能:①拦截类的创建②修改类(或者说定制类)③返回修改之后的类
究竟为什么要使用元类:元类的主要作用是创建API. -
Python实现单例模式的两种方式:
class Singleton(type):
def __init__(cls, name, bases, dict):
super(Singleton, cls).__init__(name, bases, dict)
cls.instance = None
def __call__(cls, *args, **kw):
if cls.instance is None:
cls.instance = super(Singleton, cls).__call__(*args, **kw)
return cls.instance
class MyClass(object):
__metaclass__ = Singleton
print(MyClass())
print(MyClass())