快乐学习
前程无忧、中华英才非你莫属!

Python问题解决大全来喽

前言

也是看了朋友圈的信息,突然来了灵感,竟然这么多学Python, 问题肯定有很多。
几行代码写出漂亮的报表,几行代码完全自动化,到自己了为啥就不行了呢。
原因有很多,IT培训为了达到招生的效果,肯定用最简单的代码,做出做棒的效果,即使是麻省理工的教授
教Python,刚开始的套路,其实也是酱紫,复杂的东西简单化,简单的东西细化。
当你学完Python,可以使用老师模板化的代码,完成一些特定领域的功能,完全没有问题,
当你接触新需求的时候,感觉自己的Python 白学了,写写代码,哇,报错 了,抓头,写写代码,哇出来的效果不是我想要的,小朋友你是否有很多问号?

总结Python容易产生问号的大全,参考Python社区。


Python学习交流群:367203382


1、第一种报错,不要直接在函数中使用外部变量。
x = 10
def foo():
    x += 1
    

报错信息:
UnboundLocalError: local variable 'x' referenced before assignment


报错原因:

在Python中,仅在函数内引用的变量是隐式全局变量。如果在函数体内的任何位置为变量赋值,则除非明确声明为全局,否则将其视为局部值。


解决:

x = 10
def foo():
    global x
    x += 1


使用面向对象编程

a =2
class F:
    def foo(self):
        global a
        a = a + 2
        print(a)
if __name__ == '__main__':
    F().foo()




2、如何跨模块共享全局变量

config.py:
x = 0 # Default value of the 'x' configuration setting
mod.py:
import config
config.x = 1
main.py:
import config
import mod
print(config.x)
# 请注意,出于同样的原因,使用模块也是实现Singleton设计模式的基础


3、如何将可选参数或关键字参数从一个函数传递到另一个函数

def g(x, *args, **kwargs):
    print(x,kwargs)
def f(x, *args, **kwargs):
    kwargs['width'] = '14.3c'
    g(x, *args, **kwargs)
if __name__ == '__main__':
    f(1)

4、为什么更改列表 'y' 也会更改列表 'x'?

x = []
y = x
y.append(10)
y # [10]
x # [10]
产生这种结果有两个因素:
  1. 变量只是指向具体对象的名称。 执行 y = x 并不会为列表创建一个副本 —— 它只是创建了一个新变量 y 指向 x 所指向的同一对象。 这意味着只存在一个对象(列表),x  y 都是对它的引用。
  2. 列表属于 mutable 对象,这意味着你可以改变它的内容。
在调用 append() 之后,这个可变对象的内容由 [] 变为 [10]。 由于两个变量都指向同一对象,因此使用任何一个名称所访问到的都是修改后的值 [10]
如果我们改为将不可变对象赋值给 x:
>>>
>>> x = 5  # ints are immutable
>>> y = x
>>> x = x + 1  # 5 can't be mutated, we are creating a new object here
>>> x
6
>>> y
5
我们可以看到在此情况下 x  y 就不再相等了。 这是因为整数是 immutable 对象,当我们执行 x = x + 1 时我们并不是改变了 5 这个对象的值;而是创建了一个新的对象 (整数 6) 并将其赋值给 x (也就是改变了 x 所指向的对象)。 在赋值之后我们就有了两个对象 (整数 6  5) 以及分别指向它们的两个变量 (x 现在指向 6  y 仍然指向 5)。
某些操作 (例如 y.append(10)  y.sort()) 是改变原对象,而看上去相似的另一些操作 (例如 y = y + [10]  sorted(y)) 则是创建新对象。 
通常在 Python 中 (以及在标准库的所有代码中) 会改变原对象的方法将返回 None 以帮助避免混淆这两种不同类型的操作。 
因此如果你错误地使用了 y.sort() 并期望它将返回一个经过排序的 y 的副本,你得到的结果将会是 None,这将导致你的程序产生一个容易诊断的错误。
但是,还存在一类操作,不同的类型执行相同的操作会有不同的行为:那就是增强赋值运算符。 
例如,+= 会原地改变列表,但不会改变元组或整数 (a_list += [1, 2, 3]  a_list.extend([1, 2, 3]) 一样都会改变 a_list,而 some_tuple += (1, 2, 3)  some_int += 1 则会创建新的对象)。
换而言之:
  • 如果我们有一个可变对象 (list, dict, set 等等),我们可以使用某些特定的操作来改变它,所有指向它的变量都会显示它的改变。
  • 如果我们有一个不可变对象 (str, int, tuple 等等),所有指向它的变量都将显示相同样的值,但凡是会改变这个值的操作将总是返回一个新对象。
如果你想知道两个变量是否指向相同的对象,你可以使用 is 运算符,或内置函数 id()


5、如何在Python中复制对象?

一般来说,通常情况下请尝试 copy.copy() copy.deepcopy()。 不是所有对象都可以复制,但多数都是可以的。
某些对象可以方便地复制。 例如字典具有 copy() 方法:
newdict = olddict.copy()
序列可以通过切片来复制:
new_l = l[:]

6、为什么-22 // 10返回-3?
这主要是为了让 i % j 的正负与 j 一致,如果你想要这样的结果,并且又想要:
i == (i // j) * j + (i % j)
那么整除就必须向下取整。 C 同样要求保持一致,并且编译器在截短 i // j 的结果值时需要使 i % j 的正负与 i 一致。
对于 i % j 来说 j 为负值的应用场景实际上是非常少的。 而 j 为正值的情况则非常多,并且实际上在所有情况下让 i % j 的结果为 >= 0 会更有用处。 
如果现在时间为 10 时,那么 200 小时前应是几时? -190 % 12 == 2 是有用处的;-190 % 12 == -10 则是会导致意外的漏洞。



7、如何找到对象的方法和属性

对于一个用户自定义类的实例 x,dir(x) 将返回一个按字母顺序排序的包含实例属性和方法及其类所定义的属性名称的列表


8、如何将字符串转换为数字?

对于整数,可使用内置的 int() 类型构造器,例如 int('144') == 144。 类似地,可使用 float() 转换为浮点数,例如 float('144') == 144.0。



9、如何将数字转换为字符串

要将数字144转换为字符串“ 144”,请使用内置类型构造函数str()



10、如何在适当位置修改字符串?

您不能,因为字符串是不可变的。在大多数情况下,您应该简单地从要组装字符串的各个部分中构造一个新字符串。但是,如果您需要一个具有修改就地unicode数据能力的io.StringIO对象,请尝试使用一个对象或array 模块:
import io
s = "Hello, world"
sio = io.StringIO(s)
sio.getvalue()
sio.seek(7)
sio.write("there!")
sio.getvalue()
import array
a = array.array('u', s)
print(a)
a[0] = 'y'
print(a)
a.tounicode()

11、如何使用字符串调用函数/方法?

有各种各样的技术。
最好是使用将字符串映射到函数的字典。该技术的主要优点是字符串不需要与函数名称匹配。这也是用于模拟案例构造的主要技术:

def a():
    pass
def b():
    pass
dispatch = {'go': a, 'stop': b} # Note lack of parens for funcs
dispatch[get_input()]() # Note trailing parens to call function
使用内置功能getattr()
import foo
getattr(foo, 'bar')()
请注意,它getattr()适用于任何对象,包括类,类实例,模块等。



12、将多个字符串连接在一起的最有效方法是什么?

str和bytes对象是不可变的,因此将许多字符串连接在一起效率不高,因为每次连接都会创建一个新对象。在一般情况下,总运行时成本在总字符串长度中是二次方的。
要累积许多str对象,建议的惯用法是将它们放入列表中并str.join()在最后调用:

chunks = []
for s in my_strings:
    chunks.append(s)
result = ''.join(chunks)
要累积许多bytes对象,建议的惯用法是bytearray使用就位串联(+=运算符)扩展对象:
result = bytearray()
for b in my_bytes_objects:
    result += b

13、如何在元组和列表之间转换?

类型构造函数tuple(seq)将任何序列(实际上是任何可迭代的)转换为具有相同顺序的相同项的元组




14、什么是负索引

Python序列用正数和负数索引。对于正数,0是第一个索引,1是第二个索引,依此类推。对于负索引,-1是最后一个索引,-2是倒数第二个(倒数第二个)索引,依此类推。认为seq[-n]与相同seq[len(seq)-n]。使用负索引可能非常方便。例如S[:-1],除最后一个字符外的所有字符串,这对于从字符串中删除结尾的换行符很有用。



15、如何相反的顺序遍历序列

for x in reversed(sequence):
... # do something with x ..



17、如何从列表中删除重复项

mylist = list(set(mylist))


18、你如何从列表中删除多个项目

与删除重复项一样,使用删除条件明确地反向进行迭代是一种可能。但是,使用带隐式或显式正向迭代的切片替换更容易,更快捷。这是三个变体:
mylist[:] = filter(keep_function, mylist)
mylist[:] = (x for x in mylist if keep_condition)
mylist[:] = [x for x in mylist if keep_condition]


19、如何将方法应用于一系列对象?

使用列表理解:
result = [obj.method() for obj in mylist]


20、如何按另一个列表中的值对一个列表排序

list1 = ["what", "I'm", "sorting", "by"]
list2 = ["something", "else", "to", "sort"]
pairs = zip(list1, list2)
pairs = sorted(pairs)
result = [x[1] for x in pairs]
result

21、为什么在循环中使用不同的值定义的lambda都返回相同的结果?

squares = []
for x in range(5):
    squares.append(lambda: x**2)

这将为您提供包含5个可以计算的lambda的列表x**2。你可能会想到的是,被调用时,他们将返回,分别为0,1, 4,9,和16。但是,当您实际尝试时,您会看到它们全部返回16:

squares[2]()
squares[4]()


发生这种情况是因为x它不是lambda的局部变量,而是在外部作用域中定义的,并且在调用lambda时将对其进行访问,而不是在定义时进行访问。在循环结束时,值为xis 4,因此所有函数现在都返回4**2,即16您还可以通过更改的值来验证这一点,x并查看lambda的结果如何变化:


x = 8
squares[2]()


为了避免这种情况,您需要将值保存在lambda局部变量中,以使它们不依赖于global的值x:

squares = []
for x in range(5):
    squares.append(lambda n=x: n**2)

此处,在lambda本地n=x创建一个新变量n,并在定义lambda时进行计算,以使其具有与x循环中该点相同的值这意味着的值n0 在第一个lambda中,1在第二个lambda中,2第三lambda中,依此类推。因此,每个lambda现在将返回正确的结果:

>>> squares[2]()
4
>>> squares[4]()
16

请注意,此行为不是lambda特有的,但也适用于常规函数。


打赏

未经允许不得转载:同乐学堂 » Python问题解决大全来喽

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

特别的技术,给特别的你!

联系QQ:1071235258QQ群:367203382
error: Sorry,暂时内容不可复制!