一、语言特性谈谈对 Python 和其他语言的区别
Python是面向对象的、解释型、高级编程语言。由Guido van Rossum在1991年创建。Python的设计理念就是强调代码的可读性。Python2.0在2000年发布,Python3.0在2008年发布。在Python中使用import this可以查看Python之禅。随着数据科学、人工智能、机器学习等学科的发展,Python无疑成了当下最热门的编程语言,没有之一。各种编程语言的对比是编程界经久不衰的话题,Python常常用来和R语言做对比,尤其是在数据科学领域。这儿就结合本人使用的亲身体验来比较一下Python和R。
首先作为科研人员和数据工作者,R语言是使用情况上来说,要比Python更加广泛。周围大大多数人也通常使用R,而不是Python。本人虽然平时也尝试写一些Python代码,但是主流的工作语言还是R。可以说“Python是爱好,R是工作”。当然,各个领域的使用情况可能不同。在科研领域,面对的主要对象是数据,包括对数据的整理和清洗,数据的分析等,而R语言自出生就流淌着统计的血液,在统计分析上具有先天优势。另外,广大科研人员并不关注语言是不是面对对象,他们反而觉得面向过程更简单一些。而且数据分析通常不会涉及太多代码的重用性,也不会太关注代码的效率(除非是写工具用)。
R语言在处理数据框(表)类型的东西上,更具优势。尤其是很多R包,比如data.table,tidyr,dplyr等等,还有%>%管道符号,在处理数据表上简直就是神器。虽然Python也有pandas等之类的模块,但是使用起来显然不如R语言灵活好用。另外,R语言在画图上也有很大优势,很灵活,尤其是ggplot2包,以及搭配各种配色,作出的图可以直接放在论文中的。
所以,可以看到R语言在数据清理筛选 -> 统计分析 -> 结果作图上都比Python具有优势,对于普通的科研人员来说,这些就够了,所以在这个意义上R语言要比Python好用很多。
当然,Python在处理非数据框(表)类型的数据时,比R语言更方便。尤其是处理字符串,Python特别好用,R相比就显得笨拙一些。此外,Python中的生成式也非常灵活方便。
另外,在面向对象而言,R语言也加入了一些S3,S4等类型,但是,就本人而言,R的S3和S4显得晦涩,很难以让人理解。Python中的类就显得很简洁了。简述解释型和编译型编程语言
我们通常用的计算机变成语言都是高级语言,高级语言有助于人类对语言的理解,很多单词数字等等,都是人类可以直接读懂的。但是,高级语言对计算机来说却是天书,计算机能够读懂的只有1和0,也就是我们常说的机器语言。为了让计算机能够读懂人类的高级编程语言,就需要一个转化,或者叫做翻译,将高级语言翻译机器语言【除非有大神可以直接用0和1来编写程序?】。这个翻译过程就是编译器或者解释器。那么编译器和解释器有什么区别?
1)解释器:每次翻译一个语句;分析高级语言源代码较快,但是执行代码较慢;通常没有中间对象产生,不占用额外的内存;逐行翻译,直到遇到错误,终止执行,所以比较容易定位错误,方便识别改进bug; 每次运行都依赖于源代码
2)编译器:在运行程序时,会将整个源代码读入,并全部一次性翻译成机器语言;需要很长时间去分析源代码,但是一旦翻译完成,执行会很快;在编译过程中通常会产生中间文件,需要占用其他内存空间;定位识别错误相对较难;编译完成之后,不必再依赖于源代码;典型的编译型语言有C/C++.
举一个简单的例子:你要学做一样菜,如果你是按照解释器去做,那么你会:看一眼菜谱,操作一步,然后在看一眼菜谱,再做下一步,以此类推,直到看完全部菜谱,然后完成做菜。而如果按照编译型语言去做,你会:首先花大量时间研究菜谱,弄清了做菜的每一步,烂熟于胸,然后开始做菜,这时就可以把菜谱扔到一边了,完全按照自己记忆中的步骤来做。所以,按照编译型语言的形式去做菜,一旦学会就会很看,不用每次都看菜谱,也可以避免“欲练此功,必先自宫,如不自宫,也可成功”的情况发生。
但是,说到具体的语言,必须要先强调一下,编译型还是解释型并不是一个语言本省的属性,它只是语言执行的一种属性而已。只不过,很多时候我们用的语言只是通过其中的一种方式执行,我们习惯于称之为该语言为解释型语言或者编译型语言。比如C语言,我们通常是通过C编译器来编译执行的,但是实际上C语言也可以解释执行。其次,编译并不意味着直接编译成机器语言,广义的来讲,编译是把一种语言翻译成另一种语言。比如Java编译器,并不是直接将源代码直接翻译成二进制的机器语言,而仅仅是使用javac编译器将源代码编译成了Java字节码,然后将该字节码放入到Java虚拟机JVM中等待执行。在执行的时候,由JIT编译器将字节码解释成机器语言。
扩展一下,关于安卓软件的执行方式是一个很有意思的问题,很好的展示了理解编译执行和解释执行。在安卓5.0之前,安卓软件的执行是彻底的解释型执行,边解释边运行,所以,解释型语言的弱点就凸显出来了,慢!和IOS的软件比起来,差距太大了。其后,安卓开始放弃使用边解释边执行的方式,在安装软件的时候将源代码全部一股脑的编译成字节码,这样这执行的时候,速度就快了很多。但是问题是,软件安装需要进行对全部代码进行编译,非常费时,安装一个安卓软件要花好多时间,而且相对于源代码,字节码文件要大很多,占用大量空间。在安卓7.0之后,安卓采用了一个折中的策略,并不对软件所有部分进行编译,而仅仅是对常用部分进行编译,提升了运行效率,同时也节省了一定的存储空间。但是相比于IOS的软件,安卓软件仍然显得慢一些。IOS直接把源代码编译成了机器码(这也是为什么IOS的软件通常比对应的安卓软肩大一些),相当于编译了一次,而安卓软件则要编译两次。现在火热的华为方舟编译器,似乎想按照IOS的方式,将安卓软件在用户下载安装之前直接编译成机器码,这肯定对提升安卓软件的运行速度有大大提升。通过安卓软件的发展史,可以很清楚看到编译型执行和解释型执行的优缺点。
具体到Python语言,虽然我们称之为解释型语言,但它也编译的过程。和Java类似,Python也会将源代码首先编译成Python字节码。只不过我们平时使用Python的时候很少注意到编译过程。即便是在交互环境性运行Python语句,也是要先编译成字节码,只不过这些字节码仅存在于内存中,执行结束变释放掉。但当我们导入(执行)一个Python文件时,你会在对应的文件夹下面发现一些.pyc的文件生成,这个就是Python编译的字节码文件。
参考:https://www.programiz.com/article/difference-compiler-interpreterPython的解释器种类以及相关特点?
通过上面的一个问题,虽然称Python为解释型语言,但实际上它在运行的时候也有编译的过程。相应而来的,Python有不同解释器(编译器)。
1)CPython
这是用C语言编写的Python最常用的解释器,一般认为是Python默认的解释器。能够更好的利用C语言写Python扩展。
2)Jython
2001年首次发布,使用Python和Java写的Python解释器。它可以将Python源代码编译成Java字节码,这就意味着Python可以在任何装有JVM的机器上运行。Jython同时支持静态编译和动态编译。
3)IronPython
2006年首次发布,使用C#语言编写,支持静态编译和交互模式。
此外,还有ActivePython,Nutika, PyJS, Stackless Python。
另外,还有PyPy,它不同于上面的解释器,PyPy使用Python语言RPython编写的,使用了JIT的编译方法,即在执行源代码的过程中,及时将源代码编译成CPU可执行的机器语言。所以它的不会产生中间字节码。对于一些长时间运行的程序,PyPy能够对程序进行很好的优化,缩短程序运行时间。
参考:https://dzone.com/articles/7-major-python-compilers-and-interpreters-availabl说说你知道的Python3 和 Python2 之间的区别?
Python3中,字符默认采用Unicode进行编码,而在Python2中字符串是默认ASCII来编码的。所以Python3所能包含的字符比Python2要宽泛的多。
Python3整数计算更方便。比如在Python2中,5/2=2,如果你想得到精确的值,必须使用小数点,5.0/2.0=2.5;而在Python3中,直接写5/2即可以得到精确结果2.5。在这个意义上来说,Python3使用更方便,初学人员不容易犯错。
另一个不同就是print语句。在Python3中,print("Hello"),在Python2中,print "Hello"。
此外,Python3中去掉了Python2中的xrange()函数,仅仅保存了range()函数。
等,请参考https://sebastianraschka.com/Articles/2014_python_2_3_key_diff.htmlPython3 和 Python2 中 int 和 long 区别?
Python2中int的最大值是65535,超过这个数值系统会自动设为long。Python3中,没有long类型,所有的整型都是int,具体的大小根据CPU架构不同而不同。xrange 和 range 的区别?
xrange只存在于Python2中,它实际上返回一个生成器对象。在Python2中,range返回一个具体的列表,通常其占用的内存空间要比生成器对象大,但是如果多次循环该列表,使用range要比xrange快一些。
在Python3中,不存在xrange,只有range函数,它返回一个生成器对象。
二、字符串列举 Python 中的基本数据类型?
数值型、字符串型和布尔型如何区别可变数据类型和不可变数据类型
可变类型:列表、字典、集合等
不可变类型:整型、浮点型、复数、字符串、元组等将“hello world”转换为首字母大写“Hello World”aa = "hello world"
aa.title()
## 'Hello World'如何检测字符串中只含有数字?a1 = "abc123"
a1.isnumeric()
## False
a2 = "123123"
a2.isnumeric()
## True将字符串“ilovechina”进行反转aa = "ilovechina"
aa[::-1]
## 'anihcevoli'Python 中的字符串格式化方式你知道哪些?
使用%进行格式化; 使用str.format进行格式化;使用f-string进行格式化(>3.6) 下面是几种字符串格式化实例:aa = "Ash"
print("Hello, %s" %aa)
print("Hello, {}".format(aa))
print(f'Hello, {aa}')
## Hello, Ash有一个字符串开头和末尾都有空格,比如“ adabdw ”,要求写一个函数把这个字符串的前后空格都去掉。aa = " adabdw "
aa.strip()
## 'adabdw'获取字符串”123456“最后的两个字符。aa = "1234456"
aa[-2:]
## '56'一个编码为 GBK 的字符串 S,要将其转成 UTF-8 编码的字符串,应如何操作?aa = "你好"
aa.decode('gbk').encode('utf-8')s=“info:xiaoZhang33 shandong”,用正则切分字符串输出[‘info’, ‘xiaoZhang’, ‘33’, ‘shandong’]import re
s="info:xiaoZhang 33 shandong"
re.findall(r"[a-zA-Z0-9]+",s)
## ['info', 'xiaoZhang', '33', 'shandong']怎样将字符串转换为小写?aa = "ABCabc"
aa.lower()
## 'abcabc'单引号、双引号、三引号的区别?
只要配对使用,通常没有太大区别,但是如果嵌套多个引号时,如果不使用转义符号,就应该避免使用同一种引号。a = “你好 中国”,去除多余空格只留一个空格。
题目表述不明。
三、 列表已知 AList = [1,2,3,1,2],对 AList 列表元素去重,写出具体过程。AList = [1,2,3,1,2]
set(AList)
## {1, 2, 3}如何实现 “1,2,3” 变成 [“1”,“2”,“3”]aa = "1,2,3"
aa.split(",")
## ['1', '2', '3']给定两个 list,A 和 B,找出相同元素和不同元素A = ["dd","ee","gg",3,4]
B = ["gg","ff",3,5]
set(A) - set(B)
## {'ee', 'dd', 4}
set([a for a in A if a not in B])
## {'ee', 'dd', 4}
set(B) - set(A)
## {'ff', 5}
set([b for b in B if b not in A])
## {5, 'ff'}
# 共同元素
set([ab for ab in A if ab in B])
## {3, 'gg'}[[1,2],[3,4],[5,6]]一行代码展开该列表,得出[1,2,3,4,5,6]aa = [[1,2],[3,4],[5,6]]
[i for j in aa for i in j]
## [1, 2, 3, 4, 5, 6]合并列表[1,5,7,9]和[2,2,6,8]aa = [1,5,7,9]
bb = [2,2,6,8]
aa + bb
## [1, 5, 7, 9, 2, 2, 6, 8]如何打乱一个列表的元素?import random
aa = [4,3,5,4,6,8,9,6,4]
random.shuffle(aa)
aa
## [4, 8, 5, 6, 6, 3, 4, 4, 9]
四、 字典字典操作中 del 和 pop 有什么区别dictA = {'name':'Cici','age':18}
del dictA['name']
dictA = {'name':'Cici','age':18}
dictA.pop("name")
pop返回删除的值,del不返回值按照字典的内的年龄排序
d1 = [ {‘name’:‘alice’, ‘age’:38}, {‘name’:‘bob’, ‘age’:18}, {‘name’:‘Carl’, ‘age’:28},]d1 = [
{'name':'alice', 'age':38},
{'name':'bob', 'age':18},
{'name':'Carl', 'age':28},
]
d1.sort(key = lambda x:x['age'])
d1
## [{'name': 'bob', 'age': 18}, {'name': 'Carl', 'age': 28}, {'name': 'alice', 'age': 38}]请合并下面两个字典 a = {“A”:1,“B”:2},b = {“C”:3,“D”:4}a = {"A":1,"B":2}
b = {"C":3,"D":4}
a.update(b)
print(a)
## {'A': 1, 'B': 2, 'C': 3, 'D': 4}
39.如何使用生成式的方式生成一个字典,写一段功能代码。{i:j for i in ["a","b"] for j in range(0,2)}
## {'a': 1, 'b': 1}如何把元组(“a”,“b”)和元组(1,2),变为字典{“a”:1,“b”:2}t1 = ("a","b")
t2 = (1,2)
{x:y for x,y in zip(t1,t2)}
## {'a': 1, 'b': 2}
五、综合Python 常用的数据结构的类型及其特性?
列表、元组、字典、字符串、集合等.
[图源见水印]如何将元组(“A”,“B”)和元组(1,2),合并成字典{“A”:1,“B”:2}
上题已完成Python 里面如何实现 tuple 和 list 的转换?
tuple转换为listaa = ("A","C","E")
list(aa)
## ['A', 'C', 'E']
list转换为tuplebb = ["A","C","E"]
tuple(bb)
## ('A', 'C', 'E')我们知道对于列表可以使用切片操作进行部分元素的选择,那么如何对生成器类型的对象实现相同的功能呢?
我们无法所用像列表那样的方式对生成器进行切片。如下,会出现错误t = (i for i in range(10))
t[5:8]
# Traceback (most recent call last):
# File "", line 1, in
# TypeError: 'generator' object is not subscriptable
但是我们可以使用itertoolsimport itertools
t = (i for i in range(10))
list(itertools.islice(t,3,7))
## [3, 4, 5, 6]请将[i for i in range(3)]改成生成器
可以直接将[]变为(),即可以作为生成器使用。下面比较了生成器和列表的大小import sys
# range(3)
ite = (i for i in range(3))
lis = [i for i in range(3)]
sys.getsizeof(ite)
## 88
sys.getsizeof(lis)
## 96
# range(1000)
ite = (i for i in range(1000))
lis = [i for i in range(1000)]
sys.getsizeof(ite)
## 88
sys.getsizeof(lis)
## 9024
可以看到生成器的对象大小始终不变,而列表对象的大小随着列表内元素的增加而增大。这就提示我们当要循环的元素数量很多时,使用生成器可以大大节省内存。a=“hello”和 b=“你好”编码成 bytes 类型a = "hello"
a.encode('utf-8')
## b'hello'下面的代码输出结果是什么?
a = (1,2,3,[4,5,6,7],8) a[2] = 2a = (1,2,3,[4,5,6,7],8)
a[2] = 2
## Traceback (most recent call last):
## File "", line 1, in
## TypeError: 'tuple' object does not support item assignment
提示错误,tuple是不可变对象,不能对tuple内的对象做修改。下面的代码输出的结果是什么?
a = (1,2,3,[4,5,6,7],8) a[5] = 2a = (1,2,3,[4,5,6,7],8)
a[5] = 2
## Traceback (most recent call last):
## File "", line 1, in
## TypeError: 'tuple' object does not support item assignment
同样提示错误,不能够添加tuple对象内元素
六、 操作类题目Python 交换两个变量的值x = 4
y = 5
x,y = y,x在读文件操作的时候会使用 read、readline 或者 readlines,简述它们各自的作用
假如有如下文件,aa.txt:The first line
Hello world!
The third line
Bye.ff = open("aa.txt","r")
ff.read()
ff.close()
## 'The first line\nHello world!\nThe third line\nBye.\n'
所以,当使用read()读入文件的时候,是把整个文件(包含分行符)当做一个字符串来读入内存的。如果我们需要在整个文件内进行正则搜索替换,read()会变得很方便。ff = open("aa.txt","r")
ff.readline()
## 'The first line\n'
ff.readline()
## 'Hello world!\n'
ff.readline()
## 'The third line\n'
ff.readline()
## 'Bye.\n'
ff.readline()
## ''
ff.close()
readline(),每执行一次都读入文件的一行,返回含有分行符的一个字符串。有点像生成器,适合按行操作,并且逐行读入,节省内存。ff = open("aa.txt","r")
ff.readlines()
## ['The first line\n', 'Hello world!\n', 'The third line\n', 'Bye.\n']
ff.close()
readlines()是把所有的行一次读入内存,返回一个列表,文件中的每一行都是列表的一个元素。json 序列化时,可以处理的数据类型有哪些?如何定制支持 datetime 类型?import json
import datetime
d = {"name":"Foo"}
print(json.dumps(d))
## {"name": "Foo"}
d['date'] = datetime.datetime.now()
# 此时print(json.dumps(d))会提示错误
def myconverter(o):
if isinstance(o,datetime.datetime):
return o.__str__()
print(json.dumps(d, default = myconverter))
## {"name": "Foo", "date": "2019-09-01 21:45:06.460029"}json 序列化时,默认遇到中文会转换成 unicode,如果想要保留中文怎么办?import json
d = {"name":"很好"}
print(json.dumps(d))
## {"name": "\u5f88\u597d"}
print(json.dumps(d,ensure_ascii = False))
## {"name": "很好"}有两个磁盘文件 A 和 B,各存放一行字母,要求把这两个文件中的信息合并(按字母顺序排列),输出到一个新文件 C 中。aa_file = open("A","r")
aa = aa_file.readline().strip()
bb_file = open("B","r")
bb = bb_file.readline().strip()
aa_1 = [i for i in aa]
bb_1 = [j for j in bb]
aa_1.extend(bb_1)
aa_1.sort()
cc_file = open("C","w")
cc_file.write("".join(aa_1)+"\n")
cc_file.close()
aa_file.close()
bb_file.close()如果当前的日期为 20190530,要求写一个函数输出 N 天后的日期,(比如 N 为 2,则输出 20190601)。
实例如下,扩展一下, 不把当前日期限定为20190530,而是作为一个函数的参数,可以用户设定。import sys
import numpy as np
days = {"01":31,"02":28,"03":31,"04":30,"05":31,"06":30,"07":31,"08":31,"09":30,"10":31,"11":30,"12":31}
days_leap = {"01":31,"02":29,"03":31,"04":30,"05":31,"06":30,"07":31,"08":31,"09":30,"10":31,"11":30,"12":31}
days_accum = list(np.cumsum([ days[i] for i in sorted(days.keys())]))
days_leap_accum = list(np.cumsum([ days_leap[i] for i in sorted(days_leap.keys())]))
def leapYear(current_year):
year = current_year
if year % 4 == 0 and (year % 100 !=0 or year % 400 ==0):
return True
else:
return False
def check_date(current_date):
current_date = str(current_date)
year = int(current_date[0:4])
if len(current_date) != 8:
sys.exit("Error: Check date formate!")
current_month = current_date[4:6]
if not current_month in days.keys():
sys.exit("Error: Check month formate!")
current_day = int(current_date[6:8])
if leapYear(year):
if not current_day in range(1,days_leap[current_month]):
sys.exit("Error: Check day formate!")
else:
if not current_day in range(1,days[current_month]):
sys.exit("Error: Check day formate!")
return current_date
def days2Date(t_days,leap):
''' days should between 1,366'''
if leap:
fun_accum = days_leap_accum
else:
fun_accum = days_accum
if t_days <= 31:
n_month = 1;
n_days = t_days
else:
n_month = len([i for i in fun_accum if i < t_days]) + 1
n_days = t_days - [i for i in fun_accum if i < t_days][-1]
return [n_month, n_days]
# main function
def calDate(current_date, n_lag):
'''
output the date after n days later
date formate using: 20190817
'''
current_date = check_date(current_date)
year = int(current_date[0:4])
month = int(current_date[4:6])
day = int(current_date[6:8])
#passed_month = [i for i in range(1,month)]
if leapYear(year):
passed_day = sum([days_leap[i] for i in sorted(days_leap.keys())][0:month-1]) + day
else:
passed_day = sum([days[i] for i in sorted(days.keys())][0:month-1]) + day
target_day = passed_day + n_lag
if leapYear(year):
year_days = 366
else:
year_days = 365
while (target_day - year_days > 0):
year = year + 1
target_day = target_day - year_days
if leapYear(year):
year_days = 366
else:
year_days = 365
f = [year]
f.extend(days2Date(target_day, leapYear(year)))
return f写一个函数,接收整数参数 n,返回一个函数,函数的功能是把函数的参数和 n 相乘并把结果返回。
感觉像是装饰器。下面代码会存在什么问题,如何改进?
def strappend(num): str=‘first’ for i in range(num): str+=str(i) return str
上述代码会出现下列错误:Traceback (most recent call last):
File "", line 1, in
File "", line 4, in strappend
TypeError: 'str' object is not callable
避免上述错误,将str(i)改为str[i]即可。一行代码输出 1-100 之间的所有偶数。[x for x in range(1,101) if x%2==0]list(filter(lambda x: x%2==0, range(1,101)))with 语句的作用,写一段代码?
with所用于处理文件流,使用它能够避免忘记关闭文件的错误。退出with代码段之后,所操作的文件自动关闭,释放内存。同时,使用with避免了使用try...finally...来处理异常和错误。with open("aa.txt", "r") as ff:
line_list = ff.readlines()python 字典和 json 字符串相互转化方法# python字典转换成json字符串
my_dict = {"name":"Evan","age":18,"sex":"M"}
import json
json.dumps(my_dict, sort_keys = True)
## '{"age": 18, "name": "Evan", "sex": "M"}'
#json字符串转换成Python字典
my_jstr = '{"age": 18, "name": "Evan", "sex": "M"}'
json.loads(my_jstr)
## {'age': 18, 'name': 'Evan', 'sex': 'M'}请写一个 Python 逻辑,计算一个文件中的大写字母数量total = 0
with open("aa.txt","r") as ff:
total = sum([1 for i in ff.read() if i.isupper()])
print("Total number of uppercase is:",total)
【THE END】