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 类可以实例化以创建独立的多个随机数生成器。
posted @ 2023-01-05 13:25  空白的时间  阅读(27)  评论(0编辑  收藏  举报