Python语言高频重点汇总

Python语言高频重点汇总
GitHub面试宝典仓库——点这里跳转
文章目录
Python语言高频重点汇总
**GitHub面试宝典仓库——点这里跳转**
1. 函数-传参
2. 元类
3. @staticmethod和@classmethod两个装饰器
4. 类属性和实例属性
5. Python的自省
6. 列表、集合、字典推导式
7. Python中单下划线和双下划线
8. 格式化字符串中的%和format
9. 迭代器和生成器
10. args和**kwargs
11. 面向切面编程AOP和装饰器
12. 鸭子类型
13. Python中的重载
14. 新式类和旧式类
15. `__new__`和`__init__`的区别
16. Python中的作用域
17. GIL线程全局锁
18. 协程
19. 闭包
20. lambda匿名函数
21. Python中函数式编程
22. Python中的拷贝
23. Python的垃圾回收机制
24. List
25. Python中的is
26. read, readline和readlines
27. Python2和Python3的区别
28. super init
1. 函数-传参
回到顶部
在python中,给一个函数传递参数其实是把实参这个变量对应的地址复制了一份,然后把复制的这个地址传递给函数中局部变量形参,此时实参和对应的形参都指向内存中这一个实际的对象。
第一个例子:

a = 500

def function1(a):
  print("函数中局部变量a的地址:", id(a))
  a = 100  # 更改之后
  print("指向100后的局部a 和 100的地址:", id(a), id(100))

print("全局a和500的地址:", id(a), id(500))
function1(a)
print("函数调用完之后全局a的地址:", id(a))

# 输出结果:
# 全局a和500的地址: 2272322100976 2272322100976
# 函数中局部变量a的地址: 2272322100976
# 指向100后的局部a 和 100的地址: 140730892516720 140730892516720
# 函数调用完之后全局a的地址: 2272322100976
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
我们可以看到,全局a指向500这个实体的地址,我们在调用function1函数的时候,把全局a的地址复制了一份,给了局部a,虽然全局a指向500,局部a也指向500,但是全局a和局部a是两个变量,即便名字相同,因为都指向500,所以可以看到此刻的全局a还有局部a还有500的内存地址都是同一块内存;接着在函数中局部a不再指向500了,局部a重新指向了100所在的内存地址了,这时候可以看到局部a和100指向的是同一块内存,因为整个函数调用的过程中,全局a一直指向500这个内存地址,在函数调用结束之后,局部a消亡,全局a依旧指向500,内存地址从来没有变化过。

第二个例子:

lst = []


def function2(lis: list):
  print("lis的地址:", id(lis))
  lis.append(200)
  print("append200之后lis的地址:", id(lis))

print("lst的地址", id(lst))
function2(lst)
print("函数调用之后的lst:", lst)

# 输出结果:
# lst的地址 2110929195592
# lis的地址: 2110929195592
# append200之后lis的地址: 2110929195592
# 函数调用之后的lst: [200]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
这个例子是同样的道理,lst指向[]所在的内存地址,接着调用函数,lst所指向的内存地址复制一份给了lis,然后lis在函数中通过接收到的内存地址把[]增加了一个元素200,然后调用结束lis局部变量消亡,所以lst还是指向[]这个对象所在的地址,因为在函数中,lis把这个列表修改了,所以lst通过地址找到这个列表是被修改过的。
我们可以把所有变量理解为内存中一个对象的引用,或者可以看作是C++ 中的指针类型。每一个变量记住的都是对象的地址,而对象又可以分为可变的mutable和不可变的immutable,在python中,string、tuple、数值是不可变的,list、set、dict是可修改的对象,可以通过多个变量都记住它的地址,然后通过不同变量去修改这些可修改的对象。
这是stack overflow上的解答:连接地址

2. 元类
回到顶部
元类又叫metaclass,在python中我们使用type(59)就可以知道59是int类型,但是你考虑过int类的类型吗?这就是元类问题,python中一切皆对象,就像linux中的一切皆文件哲学那么彻底,所以类也是对象,既然是对象就有类型,所有新类型的缺省都是type类型,可以修改,在python中,当我们创建一个对象的时候,它会进行类型检查,如果我们没指定类型缺省就是type类了。可以参考下图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cjAVQJAT-1574565572061)(https://github.com/duanmingpy/python-interview/blob/master/images/yuanlei.png)]

细节可以参考stack overflow的解答:连接地址

3. @staticmethod和@classmethod两个装饰器
回到顶部
在python类方法中有三中类型的方法,第一种是最普通的方法,在实例进行调用的时候会主动绑定调用的实例作为第一个参数,第二个是通过@classmethod装饰的方法,无论是类还是实例进行调用,都会自动绑定当前类作为第一个参数,第三个是通过@staticmethod装饰的方法,这种方法调用就像普通函数一样,不会进行传参数的自动绑定。
其实这三种方法的本质都是用类写一个装饰器,然后通过描述器的方法对类方法的参数进行约束,使用描述器实现的还有@property,其中前面的都是非数据描述器non-data descriper, @property则是数据描述器的实现data descriper。记得在刚学习python描述器的时候我还自己手写了@staticmethod、@classmethod还有@property这三个装饰器。
例子:

class Student:
  def __init__(self, name, age):
    self.name = name
    self.age = age

  @classmethod
  def play(cls):
    print(cls.__name__)

  @staticmethod
  def eating(student, food):
    print(f"{student} eat {food}")

tom = Student("tom", 17)
tom.play()
Student.eating("tom", "apples")

# 输出:
# Student
# tom eat apples
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
如果实在回忆不上来了(不可能的),可以参考real python 和stack overflow的解读:
real python:Instance, Class, and Static Methods — An Overview
stack overflow:What is the difference between @staticmethod and @classmethod?

4. 类属性和实例属性
回到顶部
类属性:通俗的讲是挂在类上的属性,所以只要是这个类的实例就可以

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值