我想要勋章之Python工程师初级

我想要勋章之Python工程师初级

让学习更有价值, 对站内学习社区例题精讲, 帮助各位深入理解技能树所涉及的知识.

精讲站内Python工程师初级习题, 帮助大家深入理解知识, 成功拿到用户勋章.

  • Python工程师·初级Lv1
  • Python工程师·初级Lv2
  • Python工程师·初级Lv3

Python工程师·初级Lv1

  • Hello World

    输出 "Hello,World!" 字符串,请找出以下选项中错误的选项。

    小知识: Python的创始人为 Guido van Rossum,当时他在阿姆斯特丹的荷兰数学和计算机科学研究学会工作。1989年的圣诞节期间,Guido van Rossum为了在打发时间,决心开发一个新的脚本解释编程,作为ABC语言的一种继承,替代使用Unix shell和C语言进行系统管理,担负同Amoeba操作系统(英语:Amoeba (operating system))的交互和异常处理。之所以选中Python作为编程的名字,是因为他是BBC电视剧——《蒙提·派森的飞行马戏团》(Monty Python’s Flying Circus)的爱好者。

    if __name__ == '__main__':
        str1 = "Hello,"
        str2 = "World!"
        print('str1'+'str2')
    

    解释print('str1'+'str2')应该为print(str1+str2)

  • 编程语言简史

    历史上有很多编程语言,他们在编程语言发展的过程中都起到过重要的作用。

    下面的 Python 数组包含了历史上的大部分编程语言。

    languages = ["Regional Assembly Language","Autocode","FORTRAN","IPL (LISP的先驱)","FLOW-MATIC (COBOL的先驱)","COMTRAN (COBOL的先驱)","LISP","ALGOL 58","FACT (COBOL的先驱)","COBOL","APL","Simula","SNOBOL","CPL (C的先驱)","BASIC","PL/I","BCPL (C的先驱)","Logo","Pascal","Forth","C语言","Smalltalk","Prolog","ML","Scheme","SQL","Ada","C++","Common Lisp","MATLAB","Eiffel","Objective-C","Erlang","Perl","Tcl","FL (Backus)","Haskell","Python","Visual Basic","HTML","Ruby","Lua","CLOS (part of ANSI Common Lisp)","Java","Delphi (Object Pascal)","JavaScript","PHP","REBOL","D","C#","Visual Basic .NET","F#","Scala","Factor","Windows PowerShell","Rust","Clojure","Go"]
    

    下面的 Python 数组包含了这些编程对应的创建时间。

    years = [1951, 1952, 1954, 1954, 1955, 1957, 1958, 1958, 1959, 1959, 1962, 1962, 1962, 1963, 1964, 1964, 1967 ,1968 ,1970 ,1970 ,1972 ,1972 ,1972 ,1973 ,1975 ,1978 ,1980 ,1983 ,1984 ,1984 ,1985 ,1986 ,1986 ,1987 ,1988 ,1989 ,1990 ,1991 ,1991 ,1991 ,1993 ,1993 ,1994 ,1995 ,1995 ,1995 ,1995 ,1997 ,1999 ,2001 ,2001 ,2002 ,2003 ,2003 ,2006 ,2006 ,2007 ,2009]
    

    编写一个 Python 程序,每行打印每个编程语言的名字和对应的创建时间,例如:

    Regional Assembly Language : 1951
    Autocode : 1952
    FORTRAN : 1954
    ...
    

    请找出以下代码中错误的选项。

    if __name__ == '__main__':
        languages = ...
        years = ...
        for language in languages:
            for year in years:
                print(language, ':', year)
    

    解释: 双重循环错误, 应该为单层循环.

  • Alice、Bob 和他们的朋友们

    密码学家 Rivest、Shamir、Adleman 于1977年4月撰写了一篇论文《数字签名与公钥密码学》(On Digital Signatures and Public-Key Cryptosystems),并投稿至了一个期刊上,不过很遗憾这篇论文被拒稿了。随后他们修改了论文,并将论文重新命名为《一种实现数字签名和公钥密码系统的方法》(A Method of Obtaining Digital Signatures and Public-Key Cryptosystems),最终于1978年2月成功发表于顶级期刊《ACM通信》(Communications of the ACM)。在这篇论文中,三位密码学家嫌弃使用A、B两个字母代表角色太无聊,就用Alice和Bob来代替A和B。

    在随后的几十年里密码学界又新增了很多著名人物。布鲁斯·施奈尔所著的《应用密码学》(Applied Cryptography)里详细列举了这些人物,下面是一些例子:

    crypto_roles = [
        '爱丽丝(Alice)是信息发送者。',
        '与鲍伯(Bob)是信息接受者。通例上,爱丽丝希望把一条消息发送给鲍伯。',
        '卡罗尔或查利(Carol或Charlie)是通信中的第三位参加者。',
        '戴夫(Dave)是通信中的第四位参加者。',
        '伊夫(Eve)是一位偷听者(eavesdropper),但行为通常是被动的。她拥有偷听的技术,但不会中途篡改发送的消息。在量子密码学中,伊夫也可以指环境(environment)。'
    ]
    

    Python 是一门多范式编程语言,其中包括面向对象编程。

    首先,我们用 Python 类(class) 定义一个密码城邦人物类型:

    # -*- coding: UTF-8 -*-
    class CryptographyPeople:
        def __init__(self, name_cn, name_en, role, desc):
            self.name_cn = name_cn
            self.name_en = name_en
            self.role = role
            self.desc = desc
    

    其次,我们添加一个简易的密码城邦人物解析器,它的作用是将类似’马提尔达(Matilda)是一位商人(merchant),用于电子商务。',这样的人物剧本解析成CryptographyPeople,创建一个密码城邦人物:

    # -*- coding: UTF-8 -*-
    class SimpleCryptographyPeopleParser:
        def __init__(self, text) -> None:
            self.text = text
    
        def parse(self, desc):
            # 解析名字部分
            name_cn, name_en, rest = self.parse_name(desc)
    
            # 解析角色部分
            role, rest = self.parse_role(rest)
    
            # 解析描述不符
            desc = self.parse_desc(rest)
    
            # 创建密码城邦人物
            people = CryptographyPeople(name_cn, name_en, role, desc)
    
            return people
    
        def parse_name(self, text):
            # 解析名字部分
            index = text.find('是')
            name, rest = text[0:index], text[index+1:]
    
            # 解析中英文名字
            start = name.find('(')
            end = name.find(')')
            name_cn = name[0:start]
            name_en = name[start+1:end]
    
            return name_cn.strip(), name_en.strip(), rest
    
        def parse_role(self, text):
            index1 = text.find('。')
            index2 = text.find(',')
    
            index = 0
            if index1 > 0 and index2 > 0:
                index = min(index1, index2)
            else:
                index = max(index1, index2)
    
            role, rest = text[0:index], text[index+1:len(text)-1]
    
            # 去除冗余量词
            counts = ['一名', '一位', '一个']
            for count in counts:
                role = role.replace(count, '')
            return role.strip(), rest.strip()
    
        def parse_desc(self, name_cn, name_en, role, rest):
            desc = rest
            if desc:
                # 识别自我主语
                self_list = [name_cn, '他', '她']
                for self_item in self_list:
                    desc = desc.replace(self_item, '我')
            else:
                # 补充默认描述
                desc = '很高兴认识你'
    

    最后,我们希望创建一个密码城邦,它包含 add 和 introduce 两个方法:

    # -*- coding: UTF-8 -*-
    class CryptographyCity:
        def __init__(self):
            self.peoples = []
    
        def add(self, text):
            parser = SimpleCryptographyPeopleParser(text)
            people = parser.parse(text)
            self.peoples.append(people)
    
        # TODO(YOU): 请在此实现 introduce 方法
    

    最终,我们可以构建起密码城邦,并让市民们全部自报家门:

    # -*- coding: UTF-8 -*-
    if __name__ == '__main__':
        crypto_roles = ...
    
        city = CryptographyCity()
        for crypto_role in crypto_roles:
            city.add(crypto_role)
        city.introduce()
    

    密码城邦人物的自我介绍如下:

    爱丽丝(Alice): 密码学家说我是一位信息发送者,很高兴认识你。
    鲍伯(Bob): 密码学家说我是一位信息接受者,通例上,爱丽丝希望把一条消息发送给我。
    ...
    

    请找出以下对类CryptographyCity的方法introduce的实现中,不正确的选项。

    class CryptographyCity:
        def __init__(self):
            self.peoples = []
    
        def add(self, text):
            parser = SimpleCryptographyPeopleParser(text)
            people = parser.parse(text)
            self.peoples.append(people)
    
        def introduce():
            for people in peoples:
                say(people)
    
        def say(people):
            info = f'{people.name_cn}({people.name_en}): 密码学家说我是一位{people.role}{people.desc}。'
            print(info)
    

    解释: introduce()没有带self无法访问peoples.

  • Python 安装交互式查询程序

    Python 历史上有几个重要的版本节点:

    January 1994,Python1.0 发布
    2000年10月16日,Python2.0 发布
    2010年7月3日,Python2.7 发布,这是Python2.x的最后一个版本,Python2.x 和 Python3.x不兼容
    2008年12月3日,Python3.0 发布,Python3引入多个和Python2.x不兼容的特性,Python 从2.x到3.x的迁移经历了比较长的时间,编程语言版本不兼容有时候会是个致命错误(例如Perl6),好在Python挺过来了。
    2021年10月5号,Python3.10 发布,这是目前到2021年为止最新的版本
    而最新的开发中版本是 Python3.11

    不同平台对Python环境的默认支持是不同的:

    Windows 平台没有默认安装 Python
    Linux/Mac 平台大部分默认安装了 Python2.7

    一般建议安装Python3.x 版本进行学习或开发。下面的Python字典给出了不同平台的安装信息:

    install = {
        "Windows": "请下载 Windows 安装包安装:https://www.python.org/downloads/windows/",
        "CentOS": "使用yum包管理器,执行命令:yum install -y python3",
        "Ubuntu": "使用apt-get包管理器,执行命令:apt-get install -y python3",
        "MacOS": "安装brew包管理器,然后执行命令: brew install python3",
    }
    

    基于这个信息,我们可以编写一个交互式Python程序,要求支持用户操作:

    反复输入平台快捷键字符查询不同平台应该如何快速安装 Python3.x 版本
    按q退出查询

    # -*- coding: UTF-8 -*-
    if __name__ == '__main__':
        install = {
            "Windows": "请下载 Windows 安装包安装:https://www.python.org/downloads/windows/",
            "CentOS": "使用yum包管理器,执行命令:yum install -y python3",
            "Ubuntu": "使用apt-get包管理器,执行命令:apt-get install -y python3",
            "MacOS": "安装brew包管理器,然后执行命令: brew install python3",
        }
    
        shortcut_keys = {}
        for platform in install:
            key = platform[0].lower()
            shortcut_keys[key] = platform
        
        # TODO(You): 请在此添加Python3.x安装文档交互式查询代码
    

    以下是交互式执行的操作样例:

    请选择安装平台[w/c/u/m, 按q退出]:w
    Windows: 请下载 Windows 安装包安装:https://www.python.org/downloads/windows/
    请选择安装平台[w/c/u/m, 按q退出]:c
    CentOS: 使用yum包管理器,执行命令:yum install -y python3
    请选择安装平台[w/c/u/m, 按q退出]:u
    Ubuntu: 使用apt-get包管理器,执行命令:apt-get install -y python3
    请选择安装平台[w/c/u/m, 按q退出]:m
    MacOS: 安装brew包管理器,然后执行命令: brew install python3
    请选择安装平台[w/c/u/m, 按q退出]:q
    

    以下选项中对Python3.x安装文档交互式查询代码的实现错误的是?

    while True:
        ret = input("请选择安装平台[w/c/u/m, 按q退出]:")
        platform = shortcut_keys.get(ret)
    
        if ret == 'q':
            break
        
        if platform is None:
            print("不支持的平台")
            break
        
        doc = install.get(platform)
        print(f"{platform}: {doc}")
    

    解释: 平台不对直接continue', 不要break

  • 操作系统如何运行程序

    人和操作系统如何交互?最早Ken Thompson设计Unix的时候,使用的是命令解释器,命令解释器接受用户的命令,然后解释他们并执行。

    Shell是人和机器交互的界面,分为GUI和命令行(CLI)两种方式,这里重点介绍命令行的方式。概念Shell路易斯·普赞(Louis Pouzin)在1964年至1965年间首次提出,随后在Multics(MULTiplexed Information and Computing System)项目中首次被实现出来。肯·汤普逊(Ken Thompson)以Multics上的shell为范本实现的第一个Unix壳层(Unix shell):Thompson shell。AT&T贝尔实验室的史蒂夫·伯恩在1977年实现了Bourne shell,或sh,它是Version 7 Unix默认的Unix shell,替代执行文件同为sh的Thompson shell。微软的Windows操作系统也提供了命令行壳层的功能,它们是Windows 95 / 98下的command.com、Windows NT内核下的cmd.exe以及PowerShell。

    下面的Python 列表包含了Unix系统常见的shell:

    shells = [
        'Bourne shell(sh)',
        'Almquist shell(ash)',
        'Debian Almquist shell(dash)',
        'Bourne-Again shell(bash)',
        'Korn shell(ksh)',
        'Z shell(zsh)',
        'C shell(csh)',
        'TENEX C shell(tcsh)',
        'EMACS shell (eshell)',
        'Es shell(es)',
        'esh (Unix) – Easy Shell',
        'friendly interactive shell(fish)',
        'rc shell(rc)– shell for Plan 9 from Bell Labs and Unix',
        'scsh(Scheme Shell)',
        'Stand-alone Shell(sash)',
        'BeanShell(bsh,bsh.Interpreter , bsh.Console)',
        'Rhino JavaScript壳层(org.mozilla.javascript.tools.shell.Main)'
    ]
    

    通过shell,我们可以让操作系统执行Python程序。而Python是解释型语言,源代码不是直接翻译成机器语言,而是先翻译成中间代码,再由解释器对中间代码进行解释运行。有两种执行Python程序的方式,下面的Python 字典包含了这两种方式的信息:

    # -*- coding: UTF-8 -*-
    run = {
        "repl": {
            "title": "交互式编程( Interactive )",
            "desc": [
                "打开终端,输入 python 回车",
                "进入 Python 交互式命令行",
                "输入 print('monkey king is coding!')"
            ]
        },
        "source": {
            "title": "Python 源代源文件( File )",
            "desc": [
                "使用你喜欢的编辑器拷贝本练习的代码, 保存为run.py",
                "打开终端,cd 到 run.py 保存的目录",
                "输入 python run.py"
            ]
        }
    }
    

    交互式命令行通常也称REPL,表示Read-Eval-Print-Loop,顾名思义是:读取-评估-打印-循环的意思。当你在shell环境里输入python并回车,就进入了Python的REPL环境,程序总是:

    等待用户输入 Python 代码
    当收到回车信号后就读取(Read)用户输入的 Python 代码
    解释读取到的 Python 代码(Eval)
    打印Python 代码的解释结果(Print)
    回到步骤1,循环(Loop)该过程

    实际上,我们在之前的习题里已经见过这样的程序,经过重新认识后,现在可以再次编写一个这样的REPL程序,功能需求如下:

    提示用户选择想要了解的Python 的两种运行方式
    用户选择后输出对应Python 运行方式的基本说明,如果用户输入错误则提示后让用户重新选择
    循环该过程直到用户输入q退出
    最后输出用户学习了几种运行方式

    基本代码框架如下:

    # -*- coding: UTF-8 -*-
    if __name__ == '__main__':
        run = {
            "i": {
                "title": "交互式编程( Interactive )",
                "desc": [
                    "打开终端,输入 python 回车",
                    "进入 Python 交互式命令行",
                    "输入 print('monkey king is coding!')"
                ]
            },
            "f": {
                "title": "Python 源代源文件( File )",
                "desc": [
                    "使用你喜欢的编辑器拷贝本练习的代码, 保存为run.py",
                    "打开终端,cd 到 run.py 保存的目录",
                    "输入 python run.py"
                ]
            }
        }
    
        print("有两种基本的方式运行 Python")
        for s in run:
            item = run.get(s)
            print("* {}: {}".format(s, item['title']))
    
        has_learn_i = False
        has_learn_f = False
    
        # TODO(You): 请在此实现代码
    
        if has_learn_i and has_learn_f:
            print("[2/2]您已完成两种 Python 运行方式的学习")
        elif has_learn_f:
            print("[1/2]您已完成 Python 源代码方式运行学习")
        elif has_learn_i:
            print("[1/2]您已完成 Python 交互式命令行运行学习")
        else:
            print("[0/2]您似乎跳过了运行方式的学习?期待下次光临!")
    

    程序的示例操作过程如下:

    有两种基本的方式运行 Python
    * repl: 交互式编程( Interactive )
    * source: Python 源代源文件( File )
    请选择你想了解的 Python 运行方式(输入:r/s选择,输入 q 退出):r
    0. 打开终端,输入 python 回车
    1. 进入 Python 交互式命令行
    2. 输入 print('monkey king is coding!')
    请选择你想了解的 Python 运行方式(输入:r/s选择,输入 q 退出):s
    0. 使用你喜欢的编辑器拷贝本练习的代码, 保存为run.py
    1. 打开终端,cd 到 run.py 保存的目录
    2. 输入 python run.py
    请选择你想了解的 Python 运行方式(输入:r/s选择,输入 q 退出):q
    [2/2]您已完成两种 Python 运行方式的学习
    

    以下选项是对代码中TODO部分的多种实现,你能找出实现错误的选项吗?

    while True:
        ret = input("请选择你想了解的 Python 运行方式(输入:r/s选择,输入 q 退出):")
        if ret == 'r' or ret == 's':
            has_learn_repl = ret=='r'
            has_learn_source = ret=='s'
            desc = run.get(shoutcut_keys.get(ret))['desc']
            for i in range(0, len(desc)):
                print("{}. {}".format(i, desc[i]))
        elif ret != 'q':
            print("[错误] 不支持的运行方式")
            break
        else:
            pass
    

    解释: 只有按q才退出

  • 现代集成开发环境(IDE)

    下面的Python多行字符串包含了根据搜索引擎IDE关键词频次建立的IDE排行榜数据,以下数据直接从网页https://pypl.github.io/IDE.html 右侧的表格拷贝下来:

    top_ide_trend = '''
    Rank	Change	IDE	Share	Trend
    1		Visual Studio	29.24 %	+3.5 %
    2		Eclipse	13.91 %	-2.9 %
    3		Visual Studio Code	12.07 %	+3.3 %
    4		Android Studio	9.13 %	-2.5 %
    5		pyCharm	8.43 %	+0.7 %
    6		IntelliJ	6.7 %	+0.8 %
    7		NetBeans	4.82 %	-0.3 %
    8		Sublime Text	3.49 %	-0.2 %
    9		Xcode	3.37 %	-1.2 %
    10		Atom	3.25 %	-0.5 %
    11		Code::Blocks	2.16 %	+0.2 %
    12		Vim	0.79 %	-0.1 %
    13		Xamarin	0.48 %	-0.1 %
    14		PhpStorm	0.46 %	-0.2 %
    15		geany	0.39 %	+0.2 %
    16		Komodo	0.31 %	-0.2 %
    17		Qt Creator	0.26 %	-0.0 %
    18		Emacs	0.18 %	-0.1 %
    19		JDeveloper	0.13 %	-0.0 %
    20		RAD Studio	0.08 %	-0.0 %
    21		JCreator	0.07 %	-0.0 %
    22		Light Table	0.07 %	-0.0 %
    23		MonoDevelop	0.06 %	-0.0 %
    24		SharpDevelop	0.03 %	-0.0 %
    25		Eric Python	0.03 %	-0.0 %
    26		Aptana	0.02 %	-0.0 %
    27		RubyMine	0.02 %	-0.0 %
    28		Coda 2	0.02 %	+0.0 %
    29		Monkey Studio	0.01 %	-0.0 %
    30		DrJava	0.01 %	-0.0 %
    '''
    

    事实上其中有些是编辑器,例如Vim和Sublime Text,这些编辑器有丰富的辅助开发的插件体系,因此许多程序员也会用它们来作为集成开发环境。VIM编辑器源自 Bram Moolenaar 在 80 年代末购入他的 Amiga 计算机时,Amiga 上没有他最常用的编辑器vi。Bram 从一个开源的 vi 复制 Stevie 开始,开发了 Vim 的 1.0 版本。另一个著名的编辑器是 Emacs,VIM 和 Emacs 是编辑器的两大流派。

    特别值得一提的是如果你装了VIM,在命令行里输入VIM,打开的VIM屏幕上会展示打开文本,其中文本Help poor children in Uganda!是一个线索,你可以通过搜索引擎了解这个细节。

    此外不同的编辑器的学习陡峭程度不同,下图展示了这点:

    下面的Python数组包含了一组 Python 开发常用工具信息:

    py_ide_infos = [
        "IDEL(https://docs.python.org/3/library/idle.html), Python 内置的IDE,功能比较一般。",
        "VIM(http://www.vim.org/),如果你是个VIM爱好者,可以用VIM编写Python,但是Python的缩进处理会比较麻烦。当然,你在 Linux 服务器上的时候有时候就只能用VI/VIM了。",
        "Visual Studio Code(https://code.visualstudio.com/),VSCode 对Python的支持非常友好,配合几个插件后几乎是对 Python 开发最友好的IDE了。",
        "PyCharm(https://www.jetbrains.com/pycharm/),jetbrains 出品的 PyCharm 也是 Python 开发者常用的IDE。"
    ]
    

    请编写一个 Python 比对程序,支持功能:

    解析 Python 常用开发工具信息,获得结构化信息
    解析 Python 排行榜数据,获得结构化信息
    在 Python 排行榜结构化信息中查找 Python 常用开发工具的数据
    输出合并后的结构信息

    基本的程序框架如下:

    # -*- coding: UTF-8 -*-
    def parse_ide_trend(top_ide_trend):
        top_ides = []
        top_ide_lines = top_ide_trend.split('\n')[1:]
        head = top_ide_lines[0]
        columns = head.split('\t')
        for row in top_ide_lines[1:]:
            row = row.strip()
            if row:
                cells = row.split('\t')
                top_ide = {}
                for i in range(0, len(columns)):
                    column = columns[i]
                    cell = cells[i]
                    top_ide[column] = cell
                top_ides.append(top_ide)
        return top_ides
    
    
    def parse_py_ide(py_ide_infos):
        py_ides = []
        for row in py_ide_infos:
            name_end = row.find('(')
            name = row[0:name_end]
    
            link_end = row.find(')')
            link = row[name_end+1:link_end]
    
            desc = row[link_end+2:]
            py_ides.append({'name': name, 'link': link, 'desc': desc})
    
        return py_ides
    
    
    def dump_join_result(py_ide, top_ide):
        py_ide_name = py_ide['name']
    
        print(f'Python IDE:{py_ide_name}')
        print('----------')
    
        print('* 基本信息')
        for key in py_ide:
            value = py_ide[key]
            print(f'  * {key}: {value}')
    
        print('* 排行信息')
        if top_ide:
            for key in top_ide:
                if key != 'IDE' and key != 'Change':
                    value = top_ide[key]
                    print(f'  * {key}: {value}')
        else:
            print('  * 无')
    
        print('')
    
    
    if __name__ == '__main__':
        top_ide_trend = ...
        py_ide_infos = ...
        top_ides = parse_ide_trend(top_ide_trend)
        py_ides = parse_py_ide(py_ide_infos)
    
        # TODO(You): 请在此编写比对程序
    

    比对程序的输出格式如下:

    Python IDE:IDEL
    ----------
    * 基本信息
      * name: IDEL
      * link: https://docs.python.org/3/library/idle.html
      * desc:  Python 内置的IDE,功能比较一般。
    * 排行信息
      * 无
    
    Python IDE:VIM
    ----------
    * 基本信息
      * name: VIM
      * link: http://www.vim.org/
      * desc: 如果你是个VIM爱好者,可以用VIM编写Python,但是Python的缩进处理会比较麻烦。当然,你在 Linux 服务器上的时候有时候就只能用VI/VIM了。
    * 排行信息
      * Rank: 12
      * Share: 0.79 %
      * Trend: -0.1 %
    
    Python IDE:Visual Studio Code
    ----------
    * 基本信息
      * name: Visual Studio Code
      * link: https://code.visualstudio.com/
      * desc: VSCode 对Python的支持非常友好,配合几个插件后几乎是对 Python 开发最友好的IDE了。
    * 排行信息
      * Rank: 3
      * Share: 12.07 %
      * Trend: +3.3 %
    
    Python IDE:PyCharm
    ----------
    * 基本信息
      * name: PyCharm
      * link: https://www.jetbrains.com/pycharm/
      * desc: jetbrains 出品的 PyCharm 也是 Python 开发者常用的IDE。
    * 排行信息
      * Rank: 5
      * Share: 8.43 %
      * Trend: +0.7 %
    

    以下选项是对代码中TODO部分的多种实现,你能找出以下实现错误的选项吗?

    top_ide_dict = {}
    i = 0
    while i < len(top_ides):
        top_ide_dict[top_ides[i]['IDE'].lower()] = i
        i += 1
    
    j = 0
    while j < len(py_ides):
        py_ide = py_ides[j]
        find_index = top_ide_dict.get(py_ide['name'].lower())
        find_top_ide = None
        if find_index and find_index >= 0:
            find_top_ide = top_ides[find_index]
        dump_join_result(py_ide, find_top_ide)
        j += 1
    

    解释: top_ide_dict[top_ides[i]['IDE'].lower()] = i 等于 top_ide.

    find_records = {}
    for top_ide in top_ides:
        for py_ide in py_ides:
            py_ide_name = py_ide['name']
            if not find_records.get(py_ide_name):
                if py_ide['name'].lower() == top_ide['IDE'].lower():
                    find_records[py_ide['name']] = True
                    dump_join_result(py_ide, top_ide)
    

    解释: find_records[py_ide['name']] 等于 find_records[py_ide['name'].lower()].

  • 代码规范(风格)

    一个正式的项目一般都有对应的代码规范,代码规范约定了如何在项目中编写代码。一般来说,个人开发可以使用任何自己喜欢的代码规范,但是在团队开发中,一般要遵循团队约定的代码规范。

    不同的编程语言,都有一些著名的代码规范。例如著名的K&R是指《The C Programming Language》一书的作者Kernighan和Ritchie二人,这是世界上第一本介绍C语言的书,而K&R风格即指他们在该书中书写代码所使用的风格。

    Google 有一个代码风格指引:Google Style Guides,里面包含了大部分主流编程语言的编码规范。以下Python三引号字符串摘录该规范的核心描述:

    google_style_guide = '''
    Every major open-source project has its own style guide: a set of conventions (sometimes arbitrary) about how to write code for that project. It is much easier to understand a large codebase when all the code in it is in a consistent style.
    
    “Style” covers a lot of ground, from “use camelCase for variable names” to “never use global variables” to “never use exceptions.” This project (google/styleguide) links to the style guidelines we use for Google code. If you are modifying a project that originated at Google, you may be pointed to this page to see the style guides that apply to that project.
    
    This project holds the C++ Style Guide, C# Style Guide, Swift Style Guide, Objective-C Style Guide, Java Style Guide, Python Style Guide, R Style Guide, Shell Style Guide, HTML/CSS Style Guide, JavaScript Style Guide, TypeScript Style Guide, AngularJS Style Guide, Common Lisp Style Guide, and Vimscript Style Guide. This project also contains cpplint, a tool to assist with style guide compliance, and google-c-style.el, an Emacs settings file for Google style.
    '''
    

    CodeChina上有一个中文镜像仓库:zh-google-styleguide,可以看到 Google Python 代码风格指引十分简短:python_style_rules

    此外,Python 官方代码风格文档是:PEP8。你会问PEP是什么?PEP是Python Enhancement Proposals的缩写。一个PEP是一份为Python社区提供各种增强功能的技术规格,也是提交新特性,以便让社区指出问题,精确化技术文档的提案。

    实际的开发中可以通过配置开发环境的插件来辅助自动化检查代码风格。下面的Python三引号字符串描述了一组相关信息:

    python_style_guides = '''
    * Python 代码风格指南',
        * [google-python-styleguide_zh_cn](https://zh-google-styleguide.readthedocs.io/en/latest/google-python-styleguide/python_style_rules /)
        * [PEP8](https://legacy.python.org/dev/peps/pep-0008/)
    * 代码风格和自动完成工具链
        * 基本工具
            * [pylint](https://pylint.org/)
            * [autopep8](https://pypi.org/project/autopep8/)
        * Visual Studio Code Python 开发基本插件
            * Pylance
            * Python Path
            * Python-autopep8
    '''
    

    请编写一段单词统计Python代码,统计上述两个Python三引号字符串里英文单词的词频。要求:

    单词请忽略大小写
    使用数组splits = ['\n', ' ', '-', ':', '/', '*', '_', '(', ')', '"', '”', '“',']','[']来切割单词
    输出词频最高的5个单词和词频信息。

    基本代码框架如下:

    # -*- coding: UTF-8 -*-
    def top_words(splits, text, top_n=5):
        i = 0
        word_dict = {}
        chars = []
        while i < len(text):
            c = text[i]
            if c in splits:
                # 过滤掉分隔字符串
                while i+1 < len(text) and text[i+1] in splits:
                    i += 1
                word = ''.join(chars).lower()
    
                # 统计词频
                # TODO(You): 请在此添加代码
    
                chars = []
            else:
                chars.append(c)
    
            i += 1
    
        word_list = list(word_dict.values())
        top_n = min(top_n, len(word_list))
        word_list.sort(key=lambda word_info: word_info['count'], reverse=True)
        return word_list[0:top_n]
    
    if __name__ == '__main__':
        google_style_guide = ...
        python_style_guides = ...
        splits = [' ', '-', ':', '/', '*', '_', '(', ')', '"', '”', '“']
    
        tops = top_words(splits, google_style_guide+python_style_guides)
    
        print('单词排行榜')
        print('--------')
        i = 0
        while i < len(tops):
            top = tops[i]
            word = top['word']
            count = top['count']
            print(f'{i+1}. 单词:{word}, 词频:{count}')
            i += 1
    

    预期的输出结果为:

    单词排行榜
    --------
    1. 单词:style, 词频:20
    2. 单词:guide,, 词频:13
    3. 单词:to, 词频:9
    4. 单词:python, 词频:8
    5. 单词:google, 词频:7
    

    以下选项是对代码中TODO部分的多种实现,你能找出以下实现错误的选项吗?

    if not word in word_dict:
        word_info = {'word': word, 'count': 0}
        word_dict[word] = word_info
    
    word_info['count'] += 1
    

    解释: 外面的word_info拿不到.

  • Python标准库模块导入

    Python 语言通过模块(module)来组织代码。Python 标准库十分庞大,由C语言编写的内置模块,和由 Python 编写的解决常见开发需求的模块。下面的Python数组列举了常用标准库。

    python_modules = [
      "os --- 多种操作系统接口",
      "os.path --- 常用路径操作",
      "re --- 正则表达式操作",
      "datetime --- 基本日期和时间类型",
      "heapq --- 堆队列算法",
      "enum --- 对枚举的支持",
      "math --- 数学函数",
      "random --- 生成伪随机数",
      "itertools --- 为高效循环而创建迭代器的函数",
      "functools --- 高阶函数和可调用对象上的操作",
      "shutil --- 高阶文件操作",
      "sqlite3 --- SQLite 数据库 DB-API 2.0 接口模块",
      "csv --- CSV 文件读写",
      "hashlib --- 安全哈希与消息摘要",
      "hmac --- 基于密钥的消息验证",
      "time --- 时间的访问和转换",
      "argparse --- 命令行选项、参数和子命令解析器",
      "logging --- Python 的日志记录工具",
      "threading --- 基于线程的并行",
      "multiprocessing --- 基于进程的并行",
      "socket --- 底层网络接口",
      "email --- 电子邮件与 MIME 处理包",
      "json --- JSON 编码和解码器",
      "urllib --- URL 处理模块",
      "http --- HTTP 模块"
    ]
    

    使用 import 相关的语句可以引入 Python 标准库模块。特别地,import 可以被动态的从任何地方调用。

    以下导入模块的用法中,错误的选项是?

    import time.time
    
    if __name__ == '__main__':
        print(time())
    

    解释: time() 应该 time.time().

  • 从前有座山,山上有座庙,庙里有个老和尚说:使用Python 包(package)组织代码

    稍微正式一点的项目,都会通过将代码组织成有层次结构的组织,以便于管理和持续维护。Python 通过包(package)的方式来组织代码,包是一种特殊的模块(module)。

    Python 的包有两种形式,分别是Regular packages 和 namespace packages。

    所谓 Regular packages 就是指含有__init__.py的目录,这样的包被其他模块导入的时候,会先执行目录下__init__.py里的代码。Regular packages 可以嵌套,也就是目录下的子目录也可以是一个包。例如:

    python_package_dir_example = '''
    parent/
        __init__.py
        one/
            __init__.py
            one/
                __init__.py
        two/
            __init__.py
        three/
            __init__.py
    '''
    

    而 namespace packages 也是有层次结构的模块组织,不过它未必是存在文件夹里的,可以存在Zip压缩包里,也可以存在网络上,而且子包和父包也未必要存储在同一个地方。这里忽略不展开。

    假设parent/__init__.py 里的代码是:

    # -*- coding: UTF-8 -*-
    print('从前有座山,')
    

    假设parent/one/__init__.py 里的代码是:

    # -*- coding: UTF-8 -*-
    print('山上有座庙,')
    

    假设parent/one/one/__init__.py 里的代码是:

    # -*- coding: UTF-8 -*-
    print('庙里有个老和尚,')
    

    假设parent/two/__init__.py 里的代码是:

    # -*- coding: UTF-8 -*-
    print('老和尚说:')
    

    假设parent/three/__init__.py 里的代码是:

    # -*- coding: UTF-8 -*-
    print('从前有座山,')
    

    如果一个模块被import过,Python 会将导入的模块缓存在sys.modules字典里缓存起来,再次导入的时候不会重新执行导入动作,直接从缓存里取。反之,如果我们从sys.modules里把导入的模块删除,则再次import会再次触发模块导入动作。

    利用以上知识,我们的目标是通过 import 语句导入模块,触发每个包目录下__init__.py加载时执行print语句,从而循环打印出:

    从前有座山,
    山上有座庙,
    庙里有个老和尚,
    老和尚说:
    从前有座山,
    山上有座庙,
    庙里有个老和尚,
    老和尚说:
    从前有座山,
    ...
    

    以下导入模块的用法中,不能循环打印出上述绕口令的选项是?

    import sys
    
    if __name__ == '__main__':
        while True:
            import parent
            import parent.one.one
            import parent.two
    
            del sys.modules['parent']
            del sys.modules['parent.one.one']
            del sys.modules['parent.two']
    

    解释: 顺序错了.

  • 使用相对路径导入包

    良好的包/模块组织在程序开发中有重要的作用。随着项目代码的逐渐增加,一开始的单文件程序会逐渐膨胀,所幸 Python 提供当包模式可以良好应对通常的代码分层组织。

    但是,当目录层次增加后,在下层目录里的代码引用其他目录的模块时,总是要输入全部路径有时并不方便,此时可以考虑使用 Python 的包相对路径来导入模块。

    假设如下的Python字符串描述的包目录结构:

    relative_packages = '''
    package/
        __init__.py
        subpackage1/
            __init__.py
            moduleX.py
            moduleY.py
        subpackage2/
            __init__.py
            moduleZ.py
        moduleA.py
    '''
    

    假设:

    package/subpackage1/moduleY.py 里定义了函数 spam
    package/subpackage2/moduleZ.py 里定义了函数 eggs
    package/moduleA.py 里定义了函数 foo

    以下选项都是在文件package/subpackage1/moduleX.py里导入模块的代码,请问错误的选项是哪个?你知道为什么吗?

    import ..subpackage2.moduleZ
    

    解释: import不能包括相对路径.

Python工程师·初级Lv2

TODO

Python工程师·初级Lv3

TODO


小结

精讲站内Python工程师初级习题, 帮助大家深入理解知识, 成功拿到用户勋章.

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值