关于Python中的基础问题与重点语法分析

发布时间:2022-06-30 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了关于Python中的基础问题与重点语法分析脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

目录

一、Pycharm的使用问题

二、首行缩进

三、深浅copy

四、字符编码

五、闭包函数和装饰器


  身为一个python小白,在不懈的学习了快两个月python后,已经基本学完了python的基础语法,在学习中也遇到了很多坑,现在我希望把我遇到的坑分享一下,也是关于一些基础问题,希望对刚开始学习的小伙伴可以有所帮助。同时里面也有几个python里的高级语法和难理解的概念,这里面本身也包含我自己不理解的一些点,我抱着尝试的心去讲一下,要是对里面的一些代码或者专业词汇描述有错或者讲错的话,还请专业人士指正

一、pycharm的使用问题

  相信很多人在学习的时候都下载了pycharm,身为python的一个集成开发环境,pycham觉得编程环境是最好的。除此之外我也试过vs vscode等,但我觉得都没有pycharm好用。

  1、在Pycharm上我建议下载tabnine的代码补全和汉化(汉化根据个人需要,要是英语特别好或者后期其实不用汉化,甚至用起来会很别扭)

  2、pycharm不同于idle,IDLE上使用PRint或者直接敲回车都可以实现输出,但是pycharm上必须是要加一个print的,例如这样一个查找索引值的代码和布尔类型,在IDLE中直接敲回车就可以实现,但是pycharm中的print必不可少

a=["1","2"]
print("1" in a)
print(a.index("1"))

   3、pycharm最人性话的设计可能是每日小技巧了,他会每天根据你敲的代码来给你一点小技巧使你更方便,但是这在汉化之后也也是英文显示,但是还是建议直接耐心翻译去看一下。

二、首行缩进

  这是我碰到的最难受的一个点了,有的时候你首行缩进错了pycharm并不会报错,但是会让你得到不是你想要的东西,有的时候也会大片的报错。

  而我总结了一下,主要就是逻辑问题,写程序时候的逻辑不能错,这件事干完该干什么,是并列还是包含,只要把本质弄清楚,就不会错

  1、if else elif 这是最基础的但也是在逻辑上最容易出错的,我就从我直接做的一些作业来说,例如我在之前学完循环语句和条件语句做的一个小作业,要让打印一个购物车的程序,循环打印商品列表

product=[["iphone",111],["xiaomi",222],["huawei",333]]
shopping_cart=[]
while True:
    print("-----商品列表--------")
    for index,i in enumerate(product):
        print("%s.%s   %s"%(index,i[0],i[1] ))
    choice = input("输入你想买的东西的编号:")
    if choice.isdigIT():
        choice=int(choice)
        shopping_cart.apPEnd(product[choice])
        print("Add product %s into shopping cart."%(product[choice]))
    elif choice=="q":
        print("-----你已经购买以下商品-----")
        for index,p in enumerate(shopping_cart):
            print("%s. %s   %s" % (index,i[0],i[1]))

  尤其是中间,在中间开始循环之后,利用for循环和enumerat函数将商品产生出索引值以后,if语句跟for循环是并列的,而不能将if和elif缩进进去,这样才能使if语句有效,且在elif语句输入q退出时,另一for也必须在elif语句里面这样才能退出并打印已经加入的商品列表

  2、函数类与面向对象的缩进,这两者中的语法显然比缩进重要,但是在这里也提一下,以这样的一段嵌套为例

 age=19
 def k1():
     age = 73
     print(age)

     def k2():
         print(age)
     k2()
 k1()

  调用参数位置的不同也能影响输出的结果,类与面向对象与函数相似,在调用与实例化的时候也需要注意。

  注F1a;主要在函数以及面向对象中,会出现嵌套函数以及多态问题,进而对逻辑有了更大的要求。

三、深浅copy

  这算是python里面比较难理解的一个点,容易在考试里面出到,我们先从这样一段代码然后逐步加深理解

>>>a=1
>>>b=a
>>>a=2
>>>b
1
>>>id(a)
>>>id(b)

  在这段代码里,你要是输出b的值你会发现会输出1,因为在b=a以后,b指向了1,而并不是指向a,所以b并不会跟随a改变,可以用最后两行代码来验证一下他们的内存地址(下面的代码相当于我在IDLE里面写的)

   现在我们在列表里来看一下这段代码

>>>n1=["hu","wang","iphone",1,2]
>>>n2=n1
>>>n2
["hu","wang","iphone",1,2]
>>>n1[2]="huawei"
>>>n1=["hu","wang","weawei",1,2]
>>>n2

  大家想一想,我此时输出n2会发生什么,按照上面的理解,n2是不会跟着n1改变的,但是他输出的结果和改变后的n1是一样的,这是为什么,就像我把一个东西放到杯子里面,每一个东西就是一个内存地址,现在n2直接指向了n1的内存地址,相当于n2,n1完全相同,对这两个列表进行增删查改,这两个列表也仍然相同

  但是如何将这两个列表独立呢,这是用copy可以实现

>>>n1=["hu","wang","iphone",1,2]
>>>n2=n1.copy()
>>>n1,n2
>>>(['hu', 'wang', 'iphone', 1, 2], ['hu', 'wang', 'iphone', 1, 2])

  用两种方法可以检验一下是否独立,检验内存地址和改值

>>>n1=["hu","wang","iphone",1,2]
>>>n2=n1.copy()
>>>n1,n2
>>>(['hu', 'wang', 'iphone', 1, 2], ['hu', 'wang', 'iphone', 1, 2])


>>>id(n1)
2998395112000
>>>id(n2)
2998395300480

>>>n1[1]=2
>>>n1
['hu', 2, 'iphone', 1, 2]
>>>n2
['hu', 'wang', 'iphone', 1, 2]

  此时会发现,内存地址并不一样并且修改n1后n2也不变,但是这样做又会有一个新问题,比如这样

>>>n1[1]=2
>>>n1
['hu', 2, 'iphone', 1, 2]
>>>n2
['hu', 'wang', 'iphone', 1, 2]
>>>n1.append(["3",3])
>>>n1
['hu', 2, 'iphone', 1, 2,["3",3]]
>>>n1[-1][0]="huhu"
>>>n1
['hu', 2, 'iphone', 1, 2,["huhu",3]]
>>>n2
['hu','wang', 'iphone', 1, 2,["huhu",3]]

  大家发现了什么,我在n1这个列表里加了一个列表,不是说已经独立了吗,我在修改了n1这个列表里面的列表,n2也跟着改了。这是为什么,我们所说的独立,是这个列表里面的元素独立了,即是列表里面的列表独立,为什么子列表里面的元素会变,因为子列表的元素都指向一个内存地址即这个子列表。

综上所述

  以上都是浅层次的独立了列表,所有叫浅copy,但是如何深copy呢,这是需要导入一个库,当我们导入了copy库以后,便可以完全实现深copy了。

import copy
>>>n1=['hu', 2, 'iphone', 1, 2,["3",3]]
>>>n2=n1.copy()
>>>n2
['hu', 2, 'iphone', 1, 2,["3",3]]
>>>n1[-1][0]="huhu"
>>>n1
['hu', 2, 'iphone', 1, 2,["huhu",3]]
>>>n2
['hu','wang', 'iphone', 1, 2,["3",3]]

四、字符编码

  python中的字符编码真的好复杂好复杂,甚至python2和python3也有不同,这里面也涉及到有的时候为什么你输出的结果变成了乱码,我其实也不知道我现在到底理解了没有,但是先讲一下,看看我到底能不能把这个最基本的讲清楚

1、什么是字符编码

 学计算机的朋友应该都知道,计算机只能通过0和1来识别我们的语言,所以字符编码就是将我们的语言全部转为二进制来让计算机去理解

2、一些常见的字符编码

ASCII

关于Python中的基础问题与重点语法分析

  这是美国人发明的包含了最基本的128个字符的编码表,通过这些使计算机可以了解我们的语言,但是这里面是英文字符啊,中国人要是想用怎么办,于是Unicode诞生了

②unicode

  Unicode又被称为统一码、万国码;它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。

③GB2312与GBK

  中国国家标准总局1980年发布《信息交换用汉字编码字符集》提出了GB2312编码,用于解决汉字处理的问题。1995年又颁布了《汉字编码扩展规范》(GBK)。这样就解决了我们国家的编码问题。

④UTF :UTF-8,UTF-16   UTF-32

   既然unicode这么好用,为什么不全世界一直用unicode呢,unicode存在这样的一个问题,使用unicode来表示一个字符,至少占两个字节,而ASCII码只需要一个,这样会导致浪费内存空间,所以UTF出现了,UTF就是为unicode编码设计的一种在存储和传输时节省空间的编码方案,可以理解为对unicode的一种压缩,最常用的为UTF-8

  UTF-8使用1、2、3、4个字节表示所有字符,无法满足则增加一个字节

3、python2与python3的字符编码

  python3字符串默认unicode 而文件默认编码是UTF-8,python2中,文件编码字符串编码中都为ASCII,若文件头声明gbk,则字符串编码为gbk

4、编码在windows上的显示

  这里涉及到你写的程序在终端上的运行,我也还没有学习只是简单了听了一点,例如windows智能显示unicode和gbk,否则会变成乱码。

5、字符编码的转换

  你可以通过以下代码来进行字符编码的转换

>>>s="hu"
>>>s2=1.decode("utf-8")

  总结:我对于字符编码的理解也只是这些基础知识,这里面有的东西还涉及到终端里的输出 与unicode编码的详解我都不拿出来说了,希望后续可以有大佬来进行详解。

五、闭包函数和装饰器

  关于闭包函数和装饰器,这是我讲的唯一一个高级语法,我看了视频里面说这也是在面试里比较容易出到的问题,首先何为装饰器,以我的理解,就是升级你的函数功能,但是,升级函数的方法又很多种,你可以定义多个函数,可以多次调用函数,但是、、、、

  第一,有的时候你的代码实现了功能但是却会违反一些原则,例如“开放-封闭”原则:

  开放:已实现的功能代码块不能被修改

  封闭:对现有的功能进行拓展开发

  第二,软件开发需要的是多个团队运营和调试,包含成千上万的代码,你这边实现了自己的模块,下一组的人呢,或许之后的代码就需要重复修改几千次甚至几万次或者直接报错。现在我以这样的一个功能来一步步进行讲解

  比如这样,你的老板要让你将查找数字和记录时间整合到一起,可能你会写出这样一段代码(这里引用了b站up主‘嘉然今晚枪子’的讲解视频,想学习的同学也可以去看一下)

import time
def kprint_odds():
    start_time=time.perf_counter()
    for i in range(100):
        if i in range(100):
            print(i)
    end_time=time.perf_counter()
    print("it takes {} s to find all the odds".format(end_time-start_time)
if __name__="__main__"
    print_odds()

  这一个函数你会发现你成功的实现了功能,但是你会发现一个函数两个辅助功能,有的代码里面或许不止两个辅助功能,万一出错修改非常麻烦甚至影响了主要功能,代码函数一多,这样写函数几乎就是一个灾难,于是我们可以这样修改

import time
def count_time(func):
    start_time=time.perf_counter()
    func()
    end_time=time.perf_counter()
    print("it takes {} s to find all the odds".format(end_time-start_time)
def print_odds():
    for i in range(100):
        if i%2 == 1:
            print(i) 
id __name__="__main__":
    count_time(print_odds)
        

  这样定义两个函数便可以减少错误,但是这样的写法仍有一个缺点,最后是通过在辅助函数里传入主要函数进行运行,语法上可行,在可读性上不好,给读者显示的应该是直接显示主要函数,辅助函数应该被隐藏起来,于是我们就引入闭包函数。

  闭包函数:一个函数的参数和返回值都是函数

  注:闭包本质上是一个函数

闭包函数的传入参数和返回值也都是函数

闭包函数的返回值函数是对传入函数增强后的结果

import time
def print_odds():
    for i in range(100):
        if i%2 ==1: 
            print(i)
def count_time_wrapper(func):
#闭包,用于增强函数func,给函数func增加统计时间的功能
    def improved_func():   
        start_time = time.perf_counter()
        func()
        end_time = time.perf_counter()
        print("it takes {} s to find all the odds".format(end_time - start_time))
    return improved_func

if __name__ == "__main__":
    #调用count_time_wrapper增强函数  
    print_odds = count_time_wrapper(print_odds)
    print_odds()

print(print_odds())

  这是我们手动写了一段增强函数的代码来增强函数功能

  print_odds = count_time_wrapper(print_odds)

  然而我们需要一种机制,让python解释器自动增强,这时候python装饰器就来了

import time
def count_time_wrapper(func):
    def improved_func():
        start_time = time.perf_counter()
        func()
        end_time = time.perf_counter()
        print("it takes {} s to find all the odds".format(end_time - start_time))

    return improved_func

@count_time_wrapper
def print_odds():
    for i in range(100):
        if i % 2 == 1:
            print(i)

if __name__ == "__main__":
    print_odds()

  所有python装饰器本质上就是函数闭包,并且装饰器在第一次调用被装饰函数时进行增强。

  上面的装饰器你会发现,里面并没有返回值和没有输入参数的,如果我的函数又返回值和输入参数,还能加强吗?

这里需要注意

       对于有返回值的函数,调用闭包增强后,不能成功返回,但是增强了函数的辅助功能

import time
def count_time_wrapper(func):
    def improved_func():
        start_time = time.perf_counter()
        func()
        end_time = time.perf_counter()
        print("it takes {} s to find all the odds".format(end_time - start_time))

    return improved_func

@count_time_wrapper
count=0
def count_odds():   #统计计数的个数
    for i in range(100):
        if i % 2 == 1:
           count+=1
    return count   #这里增加了函数的返回值

if __name__ == "__main__":
    print_odds()

      对于含有参数的函数,调用闭包增强后,不能成功接收参数

import time
def count_time_wrapper(func):
    def improved_func():
        start_time = time.perf_counter()
        func()
        end_time = time.perf_counter()
        print("it takes {} s to find all the odds".format(end_time - start_time))

    return improved_func

@count_time_wrapper
count=0
def count_odds(lim=1000):   #统计计数的个数  这里还增加了参数
    for i in range(100):
        if i % 2 == 1:
           count+=1
    return count   #这里增加了函数的返回值

if __name__ == "__main__":
    print_odds(lim=1000)

  但是我们如何让这个闭包接收返回值和参数呢,参考如下代码

import time
def print_odds(lim=10000):
    cnt=0
    for i in range(100):
        if i%2 ==1:
             cnt+=1
    return cnt

def count_time_wrapper(func):

    def improved_func(*args, **kwargs):   #增强函数应该吧接收到的所有参数传给原函数
        start_time = time.perf_counter()
        res=func(*args, **kwargs)         #传入参数并记录返回值
        end_time = time.perf_counter()
        print("it takes {} s to find all the odds".format(end_time - start_time))
        return res                        #返回未增强函数的返回值
    return improved_func

if __name__ == "__main__":
    print_odds = count_time_wrapper(print_odds)
    print_odds(lim=10000)

  这样我们便实现了完美的闭包,后面还有多个装饰器的问题,但我就到此为止吧。

总结

  在学习完python的基础语法之后,就可以学习网络编程和爬虫了,这又是一个漫长的道路,在编程这条路上,我需要学习的东西还很多很多,并且需要不停学习,充实自己,现在python作为世界第一编程语言,的确有一些地方相对于c和java来说使用非常方便,这是也是我第一次第一次写博客,希望大家可以支持,同时身为智能科学与技的大一新生,我也希望在编程这条路上我可以一直走下去,不断努力学习

脚本宝典总结

以上是脚本宝典为你收集整理的关于Python中的基础问题与重点语法分析全部内容,希望文章能够帮你解决关于Python中的基础问题与重点语法分析所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。