Python笔记【六】

本文为博主原创,未经许可严禁转载。
本文链接:https://blog.csdn.net/zyooooxie/article/details/108812565

继续分享下 最近学习Python的收获, 这是我的博客里 学习python的category

个人博客:https://blog.csdn.net/zyooooxie

os.getcwd()

https://docs.python.org/zh-cn/3.7/library/os.html#os.getcwd

os.getcwd() 是说当前工作路径;Return a unicode string representing the current working directory



def test_getcwd():
    abc = os.getcwd()
    print(abc)

    abc1 = os.path.join(os.getcwd(), r'csdn\zyooooxie')
    print(abc1)

    abc2 = os.path.join(abc, r'csdn\zyooooxie\123.txt')
    print(abc2)

    ABC1 = os.path.join(os.getcwd(), '\zy\csdn')
    print(ABC1)

    ABC2 = os.path.join(os.getcwd(), '\zy\csdn\\321.txt')
    print(ABC2)

    # print()
    #
    # print(os.path.abspath(abc))
    # print(os.path.abspath(abc1))
    # print(os.path.abspath(abc2))
    #
    # print()
    #
    # print(os.path.dirname(abc))
    # print(os.path.dirname(abc1))
    # print(os.path.dirname(abc2))


def test_file():
    print(__file__, '__file__')
    print(os.path.abspath(__file__))

    print(os.path.abspath(os.path.dirname(__file__)))

    print(os.path.dirname(__file__))

「当前文件路径」用 os.path.abspath(os.path.dirname(_file_))

os.mkdir()

https://docs.python.org/zh-cn/3.7/library/os.html#os.mkdir

使用os.mkdir() 创建文件夹时,我发现 有些问题:因为我使用的是Windows系统,实际 文件夹名的大小写是不敏感的


def test_mkdir():
    os.mkdir('abc123')

    print(os.path.exists('abc123'))     # True
    print(os.path.exists('ABC123'))     # True

    abc = os.path.abspath(__file__)
    abc = os.path.dirname(abc)
    os.mkdir(os.path.join(abc, 'ABC123'))           # FileExistsError

for \ while … else …

https://docs.python.org/zh-cn/3.7/tutorial/controlflow.html#break-and-continue-statements-and-else-clauses-on-loops

循环语句可能带有一个 else 子句;它会在循环遍历完列表 (使用 for) 或是在条件变为假 (使用 while) 的时候被执行,但是不会在循环被 break 语句终止时被执行。


def test_for_else(test_num: int):
    for i in range(test_num):
        if i == 10:
            break
        else:
            print('这个else属于if语句')
    else:
        print('这个else属于for语句')


test_for_else(100)
# test_for_else(3)



def test_while_else(test_num: int):
    i = 0
    while i < test_num:
        i += 1

        if i > 10:
            break
        else:
            print('这个else属于if语句')

    else:
        print('这个else属于for语句')


# test_while_else(100)
test_while_else(3)

函数标注

https://docs.python.org/zh-cn/3.7/tutorial/controlflow.html#function-annotations

形参标注的定义方式是在形参名称后加上冒号,后面跟一个表达式,该表达式会被求值为标注的值。 返回值标注的定义方式是加上一个组合符号 ->,后面跟一个表达式,该标注位于形参列表和表示 def 语句结束的冒号之间。


def test_func(test_num: int, test_list: list, test_str: str ='zyooooxie') -> str:
    print('{}-{}-{}'.format(test_num, test_list, test_str))
    return 'csdn'

print(test_func.__annotations__)

使用函数标注后,Pycharm在调此方法、使用其返回值的时候 有错误类型的形参、返回值使用错误方法 会给出 提示。

生成器表达式

很早之前 笔记【一】 就讲过 列表推导式,最初用的不熟悉时,就把 [] 写成(),

(expression for iter_val in iterable)

(expression for iter_val in iterable if cond_expr),发现 它返回的不是list,而是一个生成器对象。

https://docs.python.org/zh-cn/3.7/tutorial/classes.html#generator-expressions


def test_generator_expressions():
    # 列表推导式得到的是一个列表. 生成器表达式获取的是一个生成器

    # 生成器表达式几乎不占用内存. 使用的时候才分配和使用内存
    test_gene = (i + 33 for i in range(999999999999999999999))
    print(test_gene, type(test_gene))
    print(next(test_gene))
    print(next(test_gene))
    print(next(test_gene))

    test_gene1 = (i + 33 for i in range(99))
    print(list(test_gene1))

    # # 列表推导式比较耗内存. 一次性加载;
    # test_list = [i + 33 for i in range(999999999999999999999)]
    # print(len(test_list), type(test_list))

    # 生成器表达式如果作为某个函数的参数,则可以省略掉(),直接使用即可
    sum_g = sum(i + 33 for i in range(99))
    print(sum_g)
    sum_g = sum(test_gene1)
    print(sum_g)

    set_g = set(i * 2 for i in 'zyooooxie')
    print(set_g)

    set_g = set(i for i in 'zyooooxie')
    print(set_g)

    max_g = max(i for i in 'zyooooxie')
    print(max_g)

最初我个疑惑:为啥 不叫 元组推导式 = =

有天 忽然想到 元组是不可变序列。实际循环过程中,元素增多,那肯定不是元组了。

eval()

https://docs.python.org/zh-cn/3.7/library/functions.html#eval

简单说:

a = 654321
x = 100


def func():
    y = 200
    # eval函数的globals和locals参数都被忽略了,因此变量x和变量y都取得的是eval函数被调用环境下的作用域中的变量值
    pa = eval('x+y')
    print(pa, 'pa')

    # eval函数只提供了globals参数而忽略了locals参数,locals会取globals参数的值
    pb = eval('x+y', {
    
    'x': 1, 'y': 2})
    print(pb, 'pb')

    # eval函数的globals参数和locals都被提供了,那么eval函数会先从全部作用域globals中找到变量x, 从局部作用域locals中找到变量y 【先:局部作用域中的变量,后:全局作用域】
    pc = eval('x+y', {
    
    'x': 1, 'y': 2}, {
    
    'x1': 1, 'y': 20})
    print(pc, 'pc')

    # print()函数不是一个计算表达式,没有计算结果,因此返回值为None
    pd = eval('print(x+y,x,y)')
    print(pd, 'pd')

    # 从当前环境中访问数据,但又希望重写特定变量
    pe = eval('x+y+a', globals(), {
    
    'y': 10, 'x': 20})
    print(pe)


def test_eval_change_format():
    # 转格式

    a = '123'
    a1 = eval(a)
    print(a1, type(a1))

    b = '[1,2,3,4]'
    b1 = eval(b)
    print(b1, type(b1))

    c = '(1,23,45)'
    c1 = eval(c)
    print(c1, type(c1))

    d = '{12:23, "sd":45, 98:(1, 222, 2)}'
    d1 = eval(d)
    print(d1, type(d1))

    e = 'dict(a2=23)'
    print(eval(e))

    f = 'list((1,2,33))'
    print(eval(f))

详细说:


#  globals() 和 locals() 函数各自返回当前的全局和本地字典,因此您可以将它们传递给 eval() 或 exec() 来使用。

gl_dict = {
    
    'test': 123, 'zy': 2.22222, 'sd': 'sz'}
a = 654321
age = '全局age'

def test_eval():
    # eval(expression[, globals[, locals]])
    # expression 参数会作为一个 Python 表达式,不支持复杂的代码逻辑,例如赋值操作、循环语句等等
    
    # eval() 函数的返回值是其 expression 的执行结果,在某些情况下,它会是 None:例如当该表达式是 print() 语句
   
    d = 1
    print(d)
    # 使用已有的变量
    d = eval('d+233')
    print(d)

    test_str = 'print("123")'
    eval(test_str)

    test = 'print("test_str")'
    eval(test)
    print(test_str, '主动执行')

    eval('print(test_str)')

    a = eval('1238*44')
    print(a)

    # expression 参数是 任何代码对象(如 compile() 创建的)。
    b = eval(compile(source='76-2222', filename='<string>', mode='eval'))
    print(b)
    # 如果编译该对象时的 mode 实参是 'exec' 那么 eval() 返回值为 None 。
    c = eval(compile(source='76-22', filename='<string>', mode='exec'))
    print(c)


def test_eval2():
    # eval(expr), eval(expr, globals), eval(expr, globals, locals)

    # print(locals())
    # print(globals())
    # print('上述内容是locals()、globals()')
    print(eval('gl_dict'))

    # eval() allows you to override the globals() with your own dictionary.
    # 当locals参数为空,globals参数不为空时,先查找globals参数中是否存在变量,并计算。

    print(eval("{'test': zy}", gl_dict))
    print(eval("{'name':'zy','age':age}", {
    
    "age": 1822}))
    print(eval('[123,zy]', gl_dict))

    # 当两个参数都不为空时,先查找locals参数,再查找globals参数。
    a = 123456
    print(eval('("桃花", "梨花", a)', {
    
    }, locals()))
    print(eval('("桃花", "梨花", a)', globals(), locals()))
    print(eval('("桃花", a, zy, test)', gl_dict, locals()))

    local_dict = {
    
    'a': 'xin', 'test': 123.999999}
    print(eval('["很好", a, test, zy]', gl_dict, local_dict))

exec()

https://docs.python.org/zh-cn/3.7/library/functions.html#exec

简单说:


x = 100


def func():
    y = 500
    pa = exec('x+y')
    print(pa, 'pa')
    pb = exec('x+y', {
    
    'x': 1, 'y': 2})
    print(pb)

    pc = exec('x+y', {
    
    'x': 1, 'y': 2}, {
    
    'y': 20})
    print(pc)

    pd = exec('print(x+y,x,y)')
    print(pd, 'pd')


# func()

def func2():
    y = 50

    # globals和locals参数都被忽略了,因此变量x和变量y都取得的是exec函数被调用环境下的作用域中的变量值
    exec('print(x+y)')

    # 只提供了globals参数而忽略了locals参数,locals会取globals参数的值
    exec('print(x+y)', {
    
    'x': 1, 'y': 2})

    # globals参数和locals都被提供了,那么先:局部作用域中的变量,后:全局作用域
    exec('print(x+y)', {
    
    'x': 1, 'y': 2}, {
    
    'y': 20})

# func2()


def func3():
    y = 5

    # 可以赋值
    expr = """
z = 999
# y = 0.5
print(z+x+y)
# print(locals(),'留意下')
    """
    exec(expr)
    exec(expr, {
    
    'x': 1, 'y': 2})
    exec(expr, {
    
    'x': 11, 'y': 2, 'z': 9})
    exec(expr, {
    
    'x': 111, 'y': 2, 'z': 9}, {
    
    'z': 0.9, 'y': 2000})

    # 表达式的赋值级别: expr > locals[是否重写] > globals[是否重写]

详细说:


# object:必选参数,表示需要被指定的Python代码。它必须是字符串或code对象。如果object是一个字符串,该字符串会先被解析为一组Python语句,然后在执行(除非发生语法错误)。如果object是一个code对象,那么它只是被简单的执行。
# exec()函数的返回值只会是 None,与执行语句的结果无关,所以,将 exec() 函数赋值出去,就没有任何必要。

def test_exec():

    #  exec() may alter the variables within the calling environment.
    d = 123
    print(d, '这是1次')
    exec('print(d*3)')

    exec('d="新的123"')

    # 为啥没能修改d?
    print(d, '这是2次')

    exec('d="新的456"\nprint(d*5)')    # 为啥d变了?

    print(locals(), '单独再试')

    # 在运行期,exec() 函数动态地创建了局部变量d ,然而由于 Python 的实现机制是“运行期的局部命名空间不可改变 ”,
    exec('d="新的789"\nprint(d*2)\nprint(locals(),"就是这样")')       # locals() d的值有改动


def test_exec2():

    # exec(object), exec(object, globals), exec(object, globals, locals)
    exec('print(zy, gl_dict)')

    exec("print(zy)", gl_dict)

    abc = {
    
    'zy': 'abc_dict'}
    exec("print(zy)", globals(), abc)


def test_exec3():

    g = """
def fun():
    print('打印@@@123_ABC方法')
fun()
    """

    # eval(g)     # SyntaxError: invalid syntax
    exec(g)         # 没有报错


def test_exec4():
    # 文件内容
    with open('import_py.py', 'r', encoding='utf-8') as f:
        file = f.read()

    # eval(file)          # import time   SyntaxError: invalid syntax
    exec(file)        # 没有报错;要留意 变量的定义 NameError: name 'time' is not defined

    # 代码对象
    code = compile("print('zyooooxie')", "<string>", "exec")
    exec(code)

@File: import_py.py


def test():
    import time         # 写 最上面会报错,time没定义

    print(time.time())


test()

# if __name__ == '__main__':
#     pass
    # test()

本文链接:https://blog.csdn.net/zyooooxie/article/details/108812565

交流技术 欢迎+QQ 153132336 zy
个人博客 https://blog.csdn.net/zyooooxie

おすすめ

転載: blog.csdn.net/zyooooxie/article/details/108812565