一、语言特性

谈谈对 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.tabletidyrdplyr等等,还有%>%管道符号,在处理数据表上简直就是神器。虽然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-interpreter

Python的解释器种类以及相关特点?

通过上面的一个问题,虽然称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.html

Python3 和 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:xiaoZhang 33 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 常用的数据结构的类型及其特性?

列表、元组、字典、字符串、集合等.

Python基础试题_java

[图源见水印]

如何将元组(“A”,“B”)和元组(1,2),合并成字典{“A”:1,“B”:2}

上题已完成

Python 里面如何实现 tuple 和 list 的转换?

tuple转换为list

aa = ("A","C","E")
list(aa)
## ['A', 'C', 'E']

list转换为tuple

bb = ["A","C","E"]
tuple(bb)
## ('A', 'C', 'E')

我们知道对于列表可以使用切片操作进行部分元素的选择,那么如何对生成器类型的对象实现相同的功能呢?

我们无法所用像列表那样的方式对生成器进行切片。如下,会出现错误

t = (i for i in range(10))
t[5:8]
# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
# TypeError: 'generator' object is not subscriptable

但是我们可以使用itertools

import 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] = 2

a = (1,2,3,[4,5,6,7],8)
a[2] = 2
## Traceback (most recent call last):
##   File "<stdin>", line 1, in <module>
## TypeError: 'tuple' object does not support item assignment

提示错误,tuple是不可变对象,不能对tuple内的对象做修改。

下面的代码输出的结果是什么?

a = (1,2,3,[4,5,6,7],8) a[5] = 2

a = (1,2,3,[4,5,6,7],8)
a[5] = 2
## Traceback (most recent call last):
##  File "<stdin>", line 1, in <module>
## 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 "<stdin>", line 1, in <module>
 File "<stdin>", 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】



Python基础试题_java_02