Python:盲点

本文涵盖了Python编程中的一些常见盲点,包括import的使用、generator、深拷贝与浅拷贝的区别、numpy操作、异常处理、字符串与列表操作等。强调了在Numpy中避免对数组直接进行类型转换,以及在处理二维数组时如何实现真正的深拷贝。同时,还分享了一些编程技巧和陷阱,如三目运算符、matplotlib的legend位置、列表推导式等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 不论是import还是from...import,初始化代码都会被执行

2. if __name__ == __main__下面的语句,不会在这个py文件导入的时候调用,只会在执行这个文件的时候调用,相当于程序的入口

3. 关于import 和 from ... import

(1)import 模块 可以

(2)import 包 不可以

(3)from 包 import 模块 可以

(4)from 包 import * (这里*指函数或者类) 可以,并且这里和__all__这个东西无关

(5)from 包 import 包  不可以,没有这种写法

(6)import 包 import * (这里的import后面接的包,包里面必须含有模块,不然也是不可以的) 如果是这种写法,那么在这个包对应的__init__.py下面,必须用__all__指明对外暴露的模块,不然搜不到

(7)__all__里面装的是模块,不是包

(8)from 包 import 函数 / 类 可以

4. 关于generator, next, send和yield

# !user/bin/python
# -*- coding: UTF-8 -*-

def f():
    print('start...')
    a = yield 5
    print('a = ', a)
    b = yield 6
    print('b = ', b) # 永远不会被执行

ob = f() # 带有yield的函数就是一个生成器
res1 = next(ob) # 首次运行生成器不能传参,因为还没碰到yield,这里将执行第一个yield之前的程序,并且将yield的返回值传给res1,函数里面的a,因为没有传参进来,所以目前是None
print('res1:', res1) # 此时res1为5,程序此时停留在'a = yield 5'这一行,因为next遇到yield跳出来了
res2 = ob.send('msg') # 第二次运行生成器,此时停留在'a = yield 5'这一行,因此,a从None变成'msg',并且继续执行代码直至遇到下一个yield并停留在yield那一行然后退出
print('res2:', res2) # 此时res2返回6,然后跳出函数,b这个时候为None,可惜永远都输出不了了


# start...
# res1: 5
# a =  msg
# res2: 6

new_ob = f()
for i in new_ob:
    print(i)

# start...
# 5
# a =  None
# 6
# b =  None


5. 关于切片到底是深拷贝还是浅拷贝的问题

Python中:深拷贝,地址不同,修改不影响原来的值

Numpy中:浅拷贝,虽然地址不同,但是修改却会影响原来的值

也就是说,在Numpy中,要对Ndarray进行深拷贝的话,最好用copy函数,其他的都不好使

总结:

(1)Python中,除了直接赋值都是深拷贝

(2)Numpy中,除了copy都是浅拷贝(着重强调Numpy中的view和切片,虽然是地址会变,但是仍然会影响原来的值,故而为浅拷贝)

# !user/bin/python
# -*- coding: UTF-8 -*-

import numpy as np

# 副本:深拷贝,即内容完全相同,地址不同
# 视图:浅拷贝,共享内存

# 浅拷贝:直接赋值
a = np.arange(10)
b = a
print(id(a) == id(b)) # True

# 浅拷贝:调用view函数 / 切片
# view函数或者切片,区别于直接赋值,因为地址会改变,但是内容仍指向原来的内容
b = a.view()
print(id(a) == id(b)) # False
print(a is b) # False
b[0] = 100
print(a) # [100   1   2   3   4   5   6   7   8   9]
print(b) # [100   1   2   3   4   5   6   7   8   9]

# 浅拷贝:切片
# 会更改原来的值,但是地址不同,等同于view
print('*' * 50)
a = np.arange(10)
b = a[:]
c = a[1:]
b[0] = 101
c[0] = 102
print(a) # [101 102   2   3   4   5   6   7   8   9]
print(b) # [101 102   2   3   4   5   6   7   8   9]
print(c) # [102   2   3   4   5   6   7   8   9]
print(id(a), id(b), id(c)) # 2355930764512 2355930764592 2355913162544

# 然而,在Python中,切片却是深拷贝
print('-' * 50)
words = ['cat', 'dogdog', 'mouse']
new_words = words[:]
new_words[0] = 'puppy'
print(words) # ['cat', 'dogdog', 'mouse']
print(new_words) # ['puppy', 'dogdog', 'mouse']
print(words is new_words) # False

6. 三目运算符

x if(x>y) else y

7. matplotlib的legend要放在plot的后面

8. 想通过函数改变numpy数组的时候,这个函数一定要用np自带的函数

下面这个执行不成功,因为ff没有用np的函数

# !user/bin/python
# -*- coding: UTF-8 -*-
import numpy as np

# f = lambda x : x if x > 0 else 0
a = np.random.randn(10, 10)
def ff(x):
    if x > 0:
        return x
    else:
        return 0

def fff(x):
    return np.exp(x)

print(ff(a))

如果用fff就可以了,因为fff里面用到了numpy的函数

9. np,max和np.maximum

(1)np.max(a, axis=None, out=None, keepdims=False)

  求序列的最值

       最少接受一个参数

      axis默认为axis=0即列向,如果axis=1即横向

ex:

  • >> np.max([-2, -1, 0, 1, 2])

  • 2

 

(2)np.maximum(X, Y, out=None)

     X和Y逐位进行比较,选择最大值.

     最少接受两个参数

ex:

  • >> np.maximum([-3, -2, 0, 1, 2], 0)

  • array([0, 0, 0, 1, 2])

 

10. 捕获warnning,在需要知道warnning的时候很管用,这样可以将警告升级为异常

>>> import warnings
>>> 
>>> warnings.filterwarnings('error')
>>> 
>>> try:
...     warnings.warn(Warning())
... except Warning:
...     print 'Warning was raised as an exception!'
... 
Warning was raised as an exception!

10. 不要对np.array这样的ndarray数据进行int或者float等强制类型转化操作

11. 广播的时候不能用 += /= 这样的便捷操作符

12. 解包操作

a = (2, 3)
print(*a)
print(a)

2 3
(2, 3)

13. 2019.8.21挖坑

父类的构造函数调用了其他函数,子类重载了调用的那个函数,那么构造子类对象的时候,调用父类的构造函数的时候,是用的子类重载后的,还是父类原有的呢?

答案是重载后的。

import numpy as np
import matplotlib.pyplot as plt

class A:
    def __init__(self):
        self.hello()

    def hello(self):
        print('hello')

class B(A):
    def __init__(self, x = 5):
        super().__init__()
        self.x = x
    
    def hello(self):
        super().hello()
        print('nihao')

b = B()

hello
nihao

14. 继承的时候,super()最好写在所有代码后面,因为可能会出现重载的函数要调用子类方法或者变量的情况,如果先写super()可能会找不到子类中的对象或者方法

下面是正确输出的代码

import numpy as np
import matplotlib.pyplot as plt

class A:
    def __init__(self):
        self.hello()

    def hello(self):
        print('hello')

class B(A):
    def __init__(self, x = 5):
        self.x = x
        super().__init__()
    
    def hello(self):
        super().hello()
        print('ciaos')
        print(self.x)
        

b = B()

hello
ciaos
5

下面是错误输出的代码

import numpy as np
import matplotlib.pyplot as plt

class A:
    def __init__(self):
        self.hello()

    def hello(self):
        print('hello')

class B(A):
    def __init__(self, x = 5):
        super().__init__()
        self.x = x
    
    def hello(self):
        super().hello()
        print('ciaos')
        print(self.x)
        
        

b = B()

AttributeError: 'B' object has no attribute 'x'

15. np.random.permutation(x),x是一个一位数组或者是一个数,用于输出打乱的数据

16. 字符串去掉引号变成函数,用eval

def test():
    print('hello')


string = 'test'
eval(string)()

17. np二维矩阵随机打乱各行,列不变

import numpy as np


a = np.arange(16).reshape(4, 4)
print(a)

permutation = np.random.permutation(a.shape[0])
print(permutation)

print(a[permutation, :])

# [[ 0  1  2  3]
#  [ 4  5  6  7]
#  [ 8  9 10 11]
#  [12 13 14 15]]
# [0 3 1 2]
# [[ 0  1  2  3]
#  [12 13 14 15]
#  [ 4  5  6  7]
#  [ 8  9 10 11]]

18. sort和sorted用于对字典进行排序

## 面试很可能会遇到
dic = {'a':2,'b':1}

1、按照key排序
    d = sorted(dic.items(),key = lambda k:k[0])
 
2、按照values排序
    e = sorted(dic.items(), key = lambda k:k[1])

强烈推荐这篇博客

https://www.cnblogs.com/dyl01/p/8563550.html

19. 字典排序

items()方法返回带有键值对的数组

import numpy as np

a = {'A':1,'B':20,'C':5}
print(sorted(a.items(), key = lambda x : x[1], reverse = True))
print(a.items())

# [('B', 20), ('C', 5), ('A', 1)]
# dict_items([('A', 1), ('B', 20), ('C', 5)])

20. Pandas中,如果用字典构造系列和数据帧,如果强行指定index或者column,则以强行指定的为准,指定的index或者column中没有,但是字典本身有的数据将被忽略,指定的index或者column中有,但是字典本身没有的数据将被置NaN

21. 列表推导式实践——根据两个数组生成字典

a = [0, 1, 2, 3]
b = ['A', 'B', 'C', 'D']
c = {a[i] : b[i] for i in range(len(a))}
print(c)

{0: 'A', 1: 'B', 2: 'C', 3: 'D'}

思考:列表推导式的思想就是 [表达式 for 迭代变量 in 可迭代对象 [if 条件表达式] ]

其中迭代变量一定会出现在表达式中,那么这个表达式一定都和a和b有关,到底什么是a和b共有的呢?下标!所以用i来代替下标就好了!

22. 20191217碰到的坑

二维数组的深拷贝

如上面那张图所示,当使用[:]自以为是深拷贝,其实如果改变第二维的数值,还是浅拷贝。

当然,如果还是只改第一维,那么还是深拷贝,因为第一维的值却是不是共享同一片内存。但是第二维并不是。

所以,如果要完全的深拷贝一个二维数组,应该像下面这样。

23.  a for b in c for a in b等价于

for b in c:
    for a in b:

24. split()返回的是一个字符串list

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值