python 编程特殊问题
为什么在具有不同值的循环中定义的lambda都返回相同的结果?
# 问题: 为什么在具有不同值的循环中定义的lambda都返回相同的结果?
# 1) 列表中追加的是 lambda 函数对象
# 2) x 不是lambda本地的,而是外部作用域中定义的,
# 3)并且在调用lambda时访问它---而不是在定义lambda时访问它。在循环结束时, x 是 4 ,所有函数现在都返回 4**2 ,即 16 .
# 方式一
squares = []
for x in range(5):
squares.append(lambda: x ** 2)
print(squares[2]()) # 16
print(squares[4]()) # 16
# 方式二
squares_one = []
for x in range(5):
squares_one.append(lambda x: x ** 2)
print(squares_one[2](4)) # 16
print(squares_one[4](4)) # 16
# 解决方案
# 使 x 变成lambda 本地的变量
squares_two = []
for x in range(5):
squares_two.append(lambda n=x: n ** 2)
print(squares_two[2]()) # 4
print(squares_two[4]()) # 16
如何跨模块共享全局变量?
在单个程序中跨模块共享信息的标准方法是创建一个特殊的模块(通常称为config或cfg)。
只需在应用程序的所有模块中导入配置模块,该模块就可以作为全局名称使用。
因为每个模块只有一个实例,所以对模块对象所做的任何更改都会反映到所有地方。例如:
config.py:
x = 0
model.py:
import config
config.x = 1
main.py:
import config
import mod
print(config.x) # 1
# 请注意,出于同样的原因,使用模块也是实现单例设计模式的基础
为什么对象之间共享默认值?
- 暂时无法理解
- 文档地址
对象属性赋值便捷方法
obj = Namespace(**{'name': 'j', 'phone': 123, 'address': 'ShangHai'})
print(obj.name) # j
print(obj.phone) # 123
print(obj.address) # ShangHai
obj = Namespace(name='w', phone=321, address='BeiJing')
print(obj.name) # w
print(obj.phone) # 321
print(obj.address) # BeiJing
如何编写带有输出参数的函数(引用调用)?
方式一
# 方式一
def func1(a, b):
return 'new-value', b + 1
x, y = 'old-value', 99
func1(x, y) # ('new-value', 100)
print(func1(x, y)) # 没有理解
方式二
- 全局变量 不推荐使用,(原因是线程不安全)
- example:
param = 1 def func5(): global param param = param + 1 return param func5() print(param) # 2
方式三
def func2(a):
a[0] = 'new-value' # 'a' references a mutable list #a 是一个可变的列表
a[1] = a[1] + 1 # changes a shared object 就地改变
args = ['old-value', 99]
func2(args)
print(args)
方式四
def func3(args):
args['a'] = 'new-value' # args is a mutable dictionary
args['b'] = args['b'] + 1 # change it in-place
args = {'a': 'old-value', 'b': 99}
func3(args)
print(args)
方式五
class Namespace:
def __init__(self, **args):
for key, value in args.items():
setattr(self, key, value)
def func4(args):
args.a = 'new-value' # args is a mutable Namespace
args.b = args.b + 1 # change object in-place
args = Namespace(a='old-value', b=99)
func4(args)
print(vars(args))
- 最好的选择是返回包含多个结果的元组
如何在Python中生成高阶函数?(函数返回函数或可调用对象)
方式一
- 嵌套函数
def linear(a, b):
def result(x):
return a * x + b
return result
方式二
- 生成可调用对象 (可调用对象方法的缺点是速度较慢,导致代码稍长。)
class linear:
def __init__(self, a, b):
self.a, self.b = a, b
def __call__(self, x):
return self.a * x + self.b
class exponential(linear):
# __init__ inherited
def __call__(self, x):
return self.a * (x ** self.b)
taxes = linear(0.3, 2)
print(taxes(10e6))
# 0.3 * 10e6 + 2 # 3000002.0
方式三
class counter:
value = 0
def set(self, x):
self.value = x
def up(self):
self.value = self.value + 1
def down(self):
self.value = self.value - 1
count = counter()
inc, dec, reset = count.up, count.down, count.set
# 在这里 inc() , dec() 和 reset() 类似于共享相同计数变量的函数
生成一个计数对象, 如果再结合单例模式,变成全局对象,调用方法直接进行计数。
单例模式的计数器类(自己设计)
def singleton(cls):
# 创建一个字典用来保存被装饰类的实例对象 _instance = {}
_instance = {}
def _singleton(*args, **kwargs):
# 判断这个类有没有创建过对象,没有新创建一个,有则返回之前创建的
if cls not in _instance:
_instance[cls] = cls(*args, **kwargs)
return _instance[cls]
return _singleton
@singleton
class counter:
value = 0
def set(self, x):
self.value = x
def up(self):
self.value = self.value + 1
def down(self):
self.value = self.value - 1
count = counter()
inc, dec, reset = count.up, count.down, count.set
inc()
dec()
dec()
print(count.value)
如何在Python中复制对象?
1) 浅拷贝 copy.copy() 或 深拷贝 copy.deepcopy() 对于一般情况。并非所有对象都可以复制
2) 字典有一个 copy() dict.copy()
3) new_l = l[:]
如何使用字符串调用函数/方法?
方式一 (使用字典对象)
def a():
print('执行函数a')
def b():
print('执行函数b')
dispatch = {'go': a, 'stop': b} # Note lack of parens for funcs
dispatch['go']() # Note trailing parens to call function
方式二 (使用发射方法,getattr)
import foo
getattr(foo, 'bar')()
注意 getattr() 在任何对象上工作,包括类、类实例、模块等。
使用 locals() 要解析函数名称,请执行以下操作
def myFunc():
print("hello")
locals()['myFunc']()
# locals()
# 更新并返回表示当前本地属性的字典。
# 当它在函数块中调用时,而不是在类块中调用。注意,在模块级, locals() 和 globals() 是同一本字典。
如何创建多维列表?
可以使用提供矩阵数据类型的扩展; NumPy 是最著名的。
如何创建pyc文件
import py_compile
print(py_compile.compile('test.py')) # 返回pyc文件路径, 在当前文件目录下的路径
# pyc文件的好处, 在windows操作系统点击直接使用,前提是此电脑需要有python对应的解释器版本
当我编辑导入的模块并重新导入时,更改不会显示出来。为什么会这样?
# 出于效率和一致性的原因,python只在第一次导入模块时读取模块文件。
# 如果没有,在一个由多个模块组成的程序中,每个模块都导入相同的基本模块,
# 那么基本模块将被解析和重新解析多次。要强制重新读取已更改的模块,请执行以下操作:
import importlib
import modname # 模块名称
importlib.reload(modname) # 重新加载模块
为什么在python中没有switch或case语句?
- 对于需要从大量可能性中进行选择的情况,可以创建一个字典,将事例值映射到要调用的函数。例如::
def function_1(...):
...
functions = {'a': function_1,
'b': function_2,
'c': self.method_1, ...}
func = functions[value]
func()
- 对于对对象调用方法,可以使用 getattr() 用于检索具有特定名称的方法的内置项::
def visit_a(self, ...):
...
...
def dispatch(self, value):
method_name = 'visit_' + str(value)
method = getattr(self, method_name)
method()
如何从文档字符串创建文档?
这个 pydoc 模块可以从Python源代码中的文档字符串创建HTML。纯粹从docstrings创建API文档的另一种方法是 epydoc . Sphinx 还可以包括docstring内容
如何在一堆工作线程中包出工作?
# 最简单的方法是使用 concurrent.futures 模块,尤其是 ThreadPoolExecutor 班级。
# 或者,如果您想要对调度算法进行精细控制,您可以手动编写自己的逻辑。使用 queue 模块创建包含任务列表的队列。这个 Queue 类维护对象列表并具有 .put(obj) 将项添加到队列和 .get() 方法返回它们。该类将负责必要的锁定,以确保每项任务只分发一次。
code
import threading, queue, time
# The worker thread gets jobs off the queue. When the queue is empty, it
# assumes there will be no more work and exits.
# (Realistically workers will run until terminated.)
def worker():
print('Running worker')
time.sleep(0.1)
while True:
try:
arg = q.get(block=False)
except queue.Empty:
print('Worker', threading.currentThread(), end=' ')
print('queue empty')
break
else:
print('Worker', threading.currentThread(), end=' ')
print('running with argument', arg)
time.sleep(0.5)
# Create queue
q = queue.Queue()
# Start a pool of 5 workers
for i in range(5):
t = threading.Thread(target=worker, name='worker %i' % (i+1))
t.start()
# Begin adding work to the queue
for i in range(50):
q.put(i)
# Give threads time to run
print('Main thread sleeping')
time.sleep(5)
result
Running worker
Running worker
Running worker
Running worker
Running worker
Main thread sleeping
Worker <Thread(worker 1, started 130283832797456)> running with argument 0
Worker <Thread(worker 2, started 130283824404752)> running with argument 1
Worker <Thread(worker 3, started 130283816012048)> running with argument 2
Worker <Thread(worker 4, started 130283807619344)> running with argument 3
Worker <Thread(worker 5, started 130283799226640)> running with argument 4
Worker <Thread(worker 1, started 130283832797456)> running with argument 5
为什么关闭sys.stdout(stdin、stderr)不会真正关闭它?
- 需要关闭c描述符
要关闭这三个文件中的一个的底层C文件描述符,首先应该确保这是您真正想要做的
os.close(stdin.fileno())
os.close(stdout.fileno())
os.close(stderr.fileno())
如何从python脚本发送邮件?
方式一
import sys, smtplib
fromaddr = input("From: ")
toaddrs = input("To: ").split(',')
print("Enter message, end with ^D:")
msg = ''
while True:
line = sys.stdin.readline()
if not line:
break
msg += line
# The actual mail send
server = smtplib.SMTP('localhost')
server.sendmail(fromaddr, toaddrs, msg)
server.quit()
方式二
只有Unix才使用sendmail。sendmail程序的位置因系统而异;有时 /usr/lib/sendmail ,有时 /usr/sbin/sendmail . sendmail手册页将帮助您解决问题。以下是一些示例代码:
import os
SENDMAIL = "/usr/sbin/sendmail" # sendmail location
p = os.popen("%s -t -i" % SENDMAIL, "w")
p.write("To: receiver@example.com\n")
p.write("Subject: test\n")
p.write("\n") # blank line separating headers from body
p.write("Some text\n")
p.write("some more text\n")
sts = p.close()
if sts != 0:
print("Sendmail exit status", sts)
如何避免在套接字的connect()方法中阻塞?
这个 select 模块通常用于帮助处理套接字上的异步I/O。
为了防止TCP连接阻塞,可以将套接字设置为非阻塞模式。当你做的时候 socket.connect() ,您将立即连接(不太可能)或获取包含错误号的异常 .errno . errno.EINPROGRESS 指示连接正在进行,但尚未完成。不同的OSE将返回不同的值,因此您必须检查系统上返回的值。
你可以使用 socket.connect_ex() 方法以避免创建异常。它只返回errno值。要投票,您可以拨打 socket.connect_ex() 以后再来一次-- 0 或 errno.EISCONN 表示您已连接--或者您可以将此套接字传递给 select.select() 检查它是否可写。
注解 这个 asyncio 模块提供了一个通用的单线程并发异步库,可用于编写无阻塞的网络代码。第三方 Twisted 类库是一种流行的、功能丰富的选择。
如何在Python中实现持久对象?
这个 pickle 库模块以非常普通的方式解决了这个问题(尽管您仍然不能存储诸如打开的文件、套接字或窗口之类的内容),并且 shelve 库模块使用pickle和(g)dbm创建包含任意python对象的持久映射。
如何在Python中生成随机数? (python随机)
标准模块 random 实现随机数生成器。用法很简单:
import random
random.random()
这将返回范围[0,1]内的随机浮点数。
此模块中还有许多其他专用的生成器,例如:
randrange(a, b) 选择范围[A,B]内的整数。
uniform(a, b) 选择范围[A,B]中的浮点数。
normalvariate(mean, sdev) 采样正态(高斯)分布。
一些更高级的函数直接作用于序列,例如:
choice(S) 从给定序列中选择随机元素。
shuffle(L) 将列表随机排列。
还有一个 Random 类可以实例化以创建独立的多个随机数生成器。