目录
- 0. python 一切执行“左闭右开”
- 1. count()、max()
- 2. lambda
- 3. 什么时候用 for 循环,什么时候用while ,如何考虑?
- 4. class:属性和方法设计之初的目的/原因?以及装饰器的作用?
- 5. 赋值、引用、深拷贝、浅拷贝
- 6. 如何自己写一个不能被直接 import 访问的模块(_下划线开头)?
- 7. 如何使用 print 打印出想要的形状/格式?
- 8. if __name__=='__main__'的作用?
- 9. 类中object是什么意思?
- 10. 类中特殊方法,比如__init__的作用?
- 11. 返回列表中最值的索引
- 12. 函数参数传递:`*`和 `**`
- 13. logging.warning("Test wav file play start ...")
0. python 一切执行“左闭右开”
- range
- 切片
- …
1. count()、max()
- count:str.count(sub, start= 0,end=len(string))
count() 方法用于统计字符串里某个字符出现的次数。 - max :max(iterable, *[, default=obj, key=func]) -> value
max 为 python 自带的函数。
默认情况,结果返回可迭代的对象中最大的那个;
lst = [1,1, 2,3,4,5]
max(lst)
5
如要在比较之前修改对象或基于特定属性/索引进行比较,必须使用关键参数key。
lst = [1,1, 2,3,4,5]
max(lst, key=lambda v: lst.count(v))
1
2. lambda
- 匿名函数语法:lambda argument_list: expression
由于def语句是复合语句,它们不能用于需要表达式的地方,这就是为什么有时使用lambda的原因。
注意,lambda等同于你在一个def的return语句中。因此,不能在lambda中使用语句,只允许表达式。
3. 什么时候用 for 循环,什么时候用while ,如何考虑?
- for循环主要用在迭代可迭代对象的情况。
- while 循环主要用在需要满足一定条件为真,反复执行的情况。
(死循环+break 退出等情况。) - 部分情况下,for 循环和while 循环可以互换使用。
4. class:属性和方法设计之初的目的/原因?以及装饰器的作用?
(1)关于类:类是模板,而实例则是根据类创建的对象。
(2) 属性:类的属性是用来表明这个类是什么。
属性分为:类属性、实例属性
实例属性用于区分不同的实例;
类属性是每个实例的共有属性。
- 实例属性
实例属性的创造依靠 __init__() 方法:
class Circle(object):
def __init__(self, r):
self.r = r
类中特殊的 init() 方法,当创建实例时,init() 方法被自动调用为创建的实例增加实例属性。
面试喜欢问的问题:创建类时,类方法中的self是什么?
self 代表类的实例,是通过类创建的实例 (注意,在定义类时这个实例我们还没有创建,它表示的我们使用类时创建的那个实例)
- 类属性
如果在类上绑定属性,则所有实例都可以访问该类的属性,并且所有实例访问的类属性都是同一个!
class Circle(object):
pi = 3.14 # 类属性
(3)方法:方法是表明这个类用是来做什么。
在类的内部,使用 def 关键字来定义方法,与一般函数定义不同,类方法必须第一个参数为 self, self 代表的是类的实例(即你还未创建类的实例),其他参数和普通函数是完全一样。
class Circle(object):
pi = 3.14 # 类属性
def __init__(self, r):
self.r = r # 实例属性
def get_area(self):
""" 圆的面积 """
# return self.r**2 * Circle.pi # 通过实例修改pi的值对面积无影响,这个pi为类属性的值
return self.r**2 * self.pi # 通过实例修改pi的值对面积我们圆的面积就会改变
circle1 = Circle(1)
print(circle1.get_area()) # 调用方法 self不需要传入参数,不要忘记方法后的括号 输出 3.14
在方法的内部需要调用实例属性采用 "self.属性名 " 调用。
(4)有了装饰器可以使用 " .属性名 " 获得返回只读属性,而不是必须在类中定义方法再通过 " .属性名( ) " 这种函数调用的方法。
In [101]: class Book(object):
...: def __init__(self,name,sale):
...: self.__name = name
...: self.__sale = sale
...: @property
...: def name(self):
...: return self.__name
In [102]: a_book = Book('magic_book',100000)
In [103]: a_book.name
Out[103]: 'magic_book'
5. 赋值、引用、深拷贝、浅拷贝
(0)赋值:只是复制了对象的引用
例如,b = a ,这种情况下,b和a是一样的,他们指向同一片内存,b不过是a的别名,是引用。(里面的元素是一个东西)
赋值操作(包括对象作为参数、返回值)不会开辟新的内存空间,它只是复制了新对象的引用。 也就是说,除了b这个名字以外,没有其它的内存开销。
修改了a,就影响了b;同理,修改了b就影响了a。
(1) 浅拷贝:只拷贝第一层
- 对不可变对象进行浅拷贝,相当于深拷贝
- 对可变对象进行浅拷贝,直接修改一个不会影响另一个,但对其可变子元素的修改会影响另一个。例如,列表中嵌套列表的修改则会影响。
浅拷贝有三种形式:切片操作,工厂函数,copy模块中的copy函数。比如对上述a:
1、切片操作:b = a[:] 或者 b = [each for each in a]
2、工厂函数:b = list(a)
3、copy函数:b = a.copy(a)
(2)深拷贝:copy.deepcopy()
- 深拷贝得到的对象和原对象互不相干,修改一个不会影响另一个,这里指任何修改
深拷贝只有一种形式,copy模块中的deepcopy函数。
注:copy() 方法,有copy,copy() 和copy.deepcopy()—— 前者是浅拷贝,后者是深拷贝
浅复制是用copy,只复制父对象,不复制对象内部的子对象;深复制用deepcopy,完全复制父对象和子对象。
一句话再总结:
- 除了deepcopy都是浅拷贝,只有第一层的浅拷贝修改之后不会改变初始对象;
- 对 deepcopy后的对象进行的操作,都不再影响初始对象。
6. 如何自己写一个不能被直接 import 访问的模块(_下划线开头)?
- 如何写一个 module,保存到本地并加载?
- 如何在线写一个module并加载?
7. 如何使用 print 打印出想要的形状/格式?
真正了解 print()函数:
print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)
Prints the values to a stream, or to sys.stdout by default.
Optional keyword arguments:
file: a file-like object (stream); defaults to the current sys.stdout.
sep: string inserted between values, default a space.
end: string appended after the last value, default
- 参数 sep=’ ’ ,代表不同值之间的间隔,默认为一个空格;也可以自己设定
print('good'"morning")
print('good', 'morning', sep=' ')
- 参数 end=’\n’,代表print完成一次打印下一次打印之前自动换行;也可以自己设定,比如 end = ‘ ’ ,表示不换行而以一个空格衔接
所以, print()可以直接表示换行操作
例子:99乘法表
for i in range(1, 10):
for j in range(1, i+1):
print("{}*{}={}".format(j, i, j*i), end=' ')
print()
1*1=1
1*2=2 2*2=4
1*3=3 2*3=6 3*3=9
1*4=4 2*4=8 3*4=12 4*4=16
1*5=5 2*5=10 3*5=15 4*5=20 5*5=25
1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36
1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49
1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64
1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81
注:也可以使用 end=’\t’
8. if name=='main’的作用?
作用:使得 python 脚本只能在命令行运行,而不能被导入当做模块使用。
if __name__=='__main__':
test()
- 当我们在命令行运行hello模块文件时,Python解释器把一个特殊变量__name__置为__main__
- 而如果在其他地方导入(import)该hello模块时,if判断将失败
因此,这种if测试可以让一个模块通过命令行运行时执行一些额外的代码,最常见的就是运行测试。
注意:import 导入Python模块不起作用!!
一个python文件通常有两种使用方法,第一是作为脚本直接执行,第二是
import
到其他的 python 脚本中被调用(模块重用)执行。因此if __name__ == 'main'
: 的作用就是控制这两种情况执行代码的过程,在if __name__ == 'main'
: 下的代码只有在第一种情况下(即文件作为脚本直接执行)才会被执行,而import
到其他脚本中是不会被执行的。
注意:__name__
不带引号!!!
9. 类中object是什么意思?
使得新建的类继承了object对象,拥有了许多可操作的对象,这些都是类中的高级特性。(针对 Python 2)
在 Python 3 中已经默认就帮你加载了object了(即便你没有写上object)。
根据LEGB原则,其中最后一个B原则就是内置(built-in)命名空间,
它会将python内部的__builtin__.py实例化的内容进行检索. 什么意思呢? 这里先列出一段简短的代码。
# -.- coding:utf-8 -.-
# __author__ = 'zhengtong'
class Person(object):
name = "zhengtong"
if __name__ == "__main__":
x = Person()
通过这段代码,当我们实例化Person()这个类的时候,那x就是一个实例对象, 整个过程python除了创建Person这个类的命名空间之外(把name=”zhengtong”加入到命名空间中),还会去执行__builtin__.py中的object类,并将object类中的所有方法传承给Person(也就是说Person继承了object的所有方法)。
10. 类中特殊方法,比如__init__的作用?
在刷 leetcode 时发现,所有的 Solution 类都没有用到类的特殊函数,因此产生疑问。
拿 构造函数 init 来说,在类中定义init()方法,是为了方便创建实例的时候给实例绑定上属性,也方便类中的方法(函数)的定义。
比如定义一个矩形的类,目的是求周长和面积:
class Rectangle():
def getPeri(self,a,b):
return (a + b)*2
def getArea(self,a,b):
return a*b
rect = Rectangle()
print(rect.getPeri(3,4))
print(rect.getArea(3,4))
print(rect.__dict__)
14
12
{}
从上例中可以看到,我们在类中并没有定义init()方法,但是也能够得到类似的要求,结果返回了矩形实例rect的周长及面积。
但是,我们通过print(rect.dict)来看这个实例的属性,竟然是空的,我定义了一个矩形,按理来说它的属性应该是它的长、宽。但是它竟然没有。这就是没有定义init()的结果。
并且,在实例化对象的时候,rect = Rectangle()参数为空,没有指定a、b的值,只有在调用函数的时候才指定了。且类中定义的每个方法的参数都有a、b,这显然浪费感情,在类中直接指定方法就可以了。
上述同样的例子,采用init()方法定义类,如下:
class Rectangle():
def __init__(self,a,b):
self.a = a
self.b = b
def getPeri(self):
return (self.a + self.b)*2
def getArea(self):
return self.a * self.b
rect = Rectangle(3,4)
print(rect.getPeri())
print(rect.getArea())
print(rect.__dict__)
14
12
{'a': 3, 'b': 4}
定义完init()后,创建的每个实例都有自己的属性,也方便直接调用类中的函数。
11. 返回列表中最值的索引
lst = [40,100,1,3]
def minIndex(lst):
return min(range(len(lst)),key=lst.__getitem__)
def maxIndex(lst):
return max(range(len(lst)),key=lst.__getitem__)
print(minIndex(lst))
print(maxIndex(lst))
2
1
12. 函数参数传递:*和 **
这两种用法其实都是用来将任意个数的参数导入到 Python 函数中:
- 单星号(*):*agrs
将所有参数以元组(tuple)的形式导入
def foo(param1, *param2):
print (param1)
print (param2)
foo(1,2,3,4,5)
1
(2, 3, 4, 5)
- 双星号(**):**kwargs
双星号()将参数以字典**的形式导入
def bar(param1, **param2):
print (param1)
print (param2)
bar(1,a=2,b=3)
1
{'a': 2, 'b': 3}
13. logging.warning(“Test wav file play start …”)
学会使用 logging 模块
来记录日志,而不是通过print()函数
参考:
- python 60 天精进
- Python入门 类class 基础篇
- Python中关于对象复制有三种类型的使用方法
- python的class(类)中的object是什么意思?
- python学习——类中为什么要定义__init__()方法