你真的了解Python吗?Python一些常见问题总结(一)
- 前言
- Python40问
- 参考链接
前言
本文整理和解答了关于python的一些常见问题,由于水平有限,难免出现错漏,敬请批评改正。
Python40问
- 什么是 Python?
- Python-百度百科
- Python官网
- Python3 菜鸟教程
- Python 是一种解释型语言。这就是说,与 C 语言和 C 的衍生语言不同,Python 代码在运行之前不需要编译。其他解释型语言还包括 PHP 和 Ruby。
- Python 是动态类型语言,指的是你在声明变量时,不需要说明变量的类型。你可以直接编写类似 x=111 和 x=”I’m a string”这样的代码,程序不会报错。
- Python 非常适合面向对象的编程(OOP),因为它支持通过组合(composition)与继承(inheritance)的方式定义类(class)。
- Python 中没有访问说明符(access specifier,类似 C++中的 public 和 private),这么设计的依据是“大家都是成年人了”。
- 在 Python 语言中,函数是第一类对象(first-class objects)。这指的是它们可以被指定给变量,函数既能返回函数类型,也可以接受函数作为输入。类(class)也是第一类对象。
- Python 代码编写快,但是运行速度比编译语言通常要慢。好在 Python 允许加入基于 C语言编写的扩展,因此我们能够优化代码,消除瓶颈,这点通常是可以实现的。numpy 就是一个很好地例子,它的运行速度真的非常快,因为很多算术运算其实并不是通过 Python 实现的。
- Python 用途非常广泛——网络应用,自动化,科学建模,大数据应用,等等。它也常被用作“胶水语言”,帮助其他语言和组件改善运行状况。
- Python 让困难的事情变得容易,因此程序员可以专注于算法和数据结构的设计,而不用处理底层的细节。
- 什么是 PEP8?
- PEP8 是一个Python 代码风格指南、编程规范,内容是一些关于如何让你的程序更具可读性的建议,本文档所提供的编码规范,适用于主要的Python发行版中组成标准库的Python代码。
- PEP8 官网
- 什么是 pickling 和 unpickling?
- Pickle 模块读入任何 Python 对象,将它们转换成字符串,然后使用 dump 函数将其转储到一个文件中——这个过程叫做 pickling。
- pickle.dump(obj, file, [,protocol])
- 从存储的字符串文件中提取原始 Python 对象的过程,叫做 unpickling
- pickle.load(file)
import pickle
# 使用pickle模块将数据对象保存到文件
data1 = {'a': [1, 2.0, 3, 4+6j],
'b': ('string', u'Unicode string'),
'c': None}
data2 = (1,2,3)
selfref_list = [1, 2, 3]
selfref_list.append(selfref_list)
output = open('data.pkl', 'wb')
# Pickle字典使用协议0
pickle.dump(data1, output)
# Pickle使用协议1
pickle.dump(data2, output)
# 使用可用的最高协议Pickle列表
pickle.dump(selfref_list, output, -1)
output.close()
#使用pickle模块从文件中重构python对象
pkl_file = open('data.pkl', 'rb')
data1 = pickle.load(pkl_file)
print(data1)
data2 = pickle.load(pkl_file)
print(data2)
data3 = pickle.load(pkl_file)
print(data3)
pkl_file.close()
{'a': [1, 2.0, 3, (4+6j)], 'b': ('string', 'Unicode string'), 'c': None}
(1, 2, 3)
[1, 2, 3, [...]]
- Python 是如何被解释的?
- Python 是一种解释性语言,它的源代码可以直接运行。Python 解释器会将源代码转换成中间语言,之后再翻译成机器码再执行。
- Python 是怎样管理内存的?
- Python 的内存管理是由私有 heap 空间管理的。所有的 Python 对象和数据结构都在一个私有 heap 中。程序员没有访问该 heap 的权限,只有解释器才能对它进行操作。
- Python 的 heap 空间分配内存是由 Python 的内存管理模块进行的,其核心 API 会提供一些访问该模块的方法供程序员使用。
- Python 有自带的垃圾回收系统,它回收并释放没有被使用的内存,让它们能够被其他程序使用。
- 有哪些工具可以帮助 debug 或做静态分析?
- PyChecker 是一个静态分析工具,它不仅能报告源代码中的错误,并且会报告错误类型和复杂度。
- Pylint 是检验模块是否达到代码标准的另一个工具。
- 什么是 Python 装饰器?
- Python 装饰器是 Python 中的特有变动,可以使修改函数变得更容易。
- 装饰器(Decorators)是 Python 的一个重要部分。
- 简单地说:他们是修改其他函数的功能的函数(封装函数)。他们有助于让我们的代码更简短。
def a_new_decorator(a_func):
def wrapTheFunction():
print("I am doing some boring work before executing a_func()")
a_func()
print("I am doing some boring work after executing a_func()")
return wrapTheFunction
def a_function_requiring_decoration():
print("I am the function which needs some decoration to remove my foul smell")
a_function_requiring_decoration()
# 现在a_function_requiring_decoration被wrapTheFunction()包装了
a_function_requiring_decoration = a_new_decorator(a_function_requiring_decoration)
print('装饰后:')
a_function_requiring_decoration()
I am the function which needs some decoration to remove my foul smell
装饰后:
I am doing some boring work before executing a_func()
I am the function which needs some decoration to remove my foul smell
I am doing some boring work after executing a_func()
上面,这正是 python 中装饰器做的事情!它们封装一个函数,并且用这样或者那样的方式来修改它的行为。现在你也许疑惑,我们在代码里并没有使用 @ 符号?那只是一个简短的方式来生成一个被装饰的函数。这里是我们如何使用 @ 来运行之前的代码:
from functools import wraps
def decorator_name(f):
@wraps(f)
def decorated(*args, **kwargs):
if not can_run:
return "Function will not run"
return f(*args, **kwargs)
return decorated
@decorator_name # 装饰器,相当于decorator_name(func)
def func():
return("Function is running")
can_run = True
print(func())# Function is running
can_run = False
print(func()) # Function will not run
Function is running
Function will not run
注意:@wraps接受一个函数来进行装饰,并加入了复制函数名称、注释文档、参数列表等等的功能。这可以让我们在装饰器里面访问在装饰之前的函数的属性。
装饰器能有助于检查某个人是否被授权去使用一个web应用的端点(endpoint)。它们被大量使用于Flask和Django web框架中。
日志是装饰器运用的另一个亮点。例如:
from functools import wraps
def logit(func):
@wraps(func)
def with_logging(*args, **kwargs):
print(func.__name__ + " was called")
return func(*args, **kwargs)
return with_logging
@logit # 装饰器,相当于logit(addition_func)
def addition_func(x):
return x + x
result = addition_func(4)# addition_func was called
print(result)
addition_func was called
8
- 数组和元组之间的区别是什么?
- 数组和元组之间的区别:数组内容是可以被修改的,而元组内容是只读的。另外,元组可以被哈希,比如作为字典的关键字。
hash((0,1,2)) # 元组可以被哈希,得到对应的哈希值
1267305975155491464
- 参数按值传递和引用传递是怎样实现的?
- Python 中的一切都是类,所有的变量都是一个对象的引用。引用的值是由函数确定的,因此无法被改变。但是如果一个对象是可以被修改的,你可以改动对象。
- 可更改(mutable)与不可更改(immutable)对象
- 在 python 中,strings, tuples, 和 numbers 是不可更改的对象,而 list,dict 等则是可以修改的对象。
- 不可变类型:变量赋值 a=5 后再赋值 a=10,这里实际是新生成一个 int 值对象 10,再让 a 指向它,而 5 被丢弃,不是改变 a 的值,相当于新生成了 a。
- 可变类型:变量赋值 la=[1,2,3,4] 后再赋值 la[2]=5 则是将 list la 的第三个元素值更改,本身la没有动,只是其内部的一部分值被修改了。
- python 函数的参数传递:
- 不可变类型:类似 C++ 的值传递,如整数、字符串、元组。如 fun(a),传递的只是 a 的值,没有影响 a 对象本身。如果在 fun(a) 内部修改 a 的值,则是新生成一个 a 的对象。
- 可变类型:类似 C++ 的引用传递,如 列表,字典。如 fun(la),则是将 la 真正的传过去,修改后 fun 外部的 la 也会受影响
- python 中一切都是对象,严格意义我们不能说值传递还是引用传递,我们应该说传不可变对象和传可变对象。
def change(a):
print(id(a)) # 指向的是同一个对象
a=10
print(id(a)) # 一个新对象
a=1
print(id(a))
change(a) # 传不可变对象实例
1359458496
1359458496
1359458784
可以看见在调用函数前后,形参和实参指向的是同一个对象(对象 id 相同),在函数内部修改形参后,形参指向的是不同的 id。
- 传可变对象实例
可变对象在函数里修改了参数,那么在调用这个函数的函数里,原始的参数也被改变了。例如:
# 可写函数说明
def change2(mylist):
"修改传入的列表"
mylist.append([1,2,3,4])
print ("函数内取值: ", mylist)
print("函数内id(mylist):",id(mylist))
return
# 调用change2函数
mylist = [10,20,30]
print("函数外id(mylist):",id(mylist))
change2(mylist)
print ("函数外取值: ", mylist)
函数外id(mylist): 2594297892744
函数内取值: [10, 20, 30, [1, 2, 3, 4]]
函数内id(mylist): 2594297892744
函数外取值: [10, 20, 30, [1, 2, 3, 4]]
- 字典推导式和列表推导式是什么?
- 它们是可以轻松创建字典和列表的语法结构。
- 列表推导式 – 计算 30 以内可以被 3 整除的整数:
multiples = [i for i in range(30) if i % 3 == 0]
print(multiples)
[0, 3, 6, 9, 12, 15, 18, 21, 24, 27]
- 字典推导式 – 提供三个数字,以三个数字为键,三个数字的平方为值来创建字典:
dic = {x: x**2 for x in (2, 4, 6)}
print(dic)
print(type(dic))
{2: 4, 4: 16, 6: 36}
- Python 都有哪些自带的数据结构?
- Python 自带的数据结构分为可变的和不可变的。
- 可变的有:数组、集合、字典;
- 不可变的有:字符串、元组、数
- 什么是 Python 的命名空间?
- 在 Python 中,所有的名字都存在于一个空间中,它们在该空间中存在和被操作——这就是命名空间。
- 它就好像一个盒子,每一个变量名字都对应装着一个对象。当查询变量的时候,会从该盒子里面寻找相应的对象
- 命名空间(Namespace)是从名称到对象的映射,大部分的命名空间都是通过 Python 字典来实现的。
- 命名空间提供了在项目中避免名字冲突的一种方法。各个命名空间是独立的,没有任何关系的,所以一个命名空间中不能有重名,但不同的命名空间是可以重名而没有任何影响。
# var1 是全局名称
var1 = 5
def some_func():
# var2 是局部名称
var2 = 6
def some_inner_func():
# var3 是内嵌的局部名称
var3 = 7
- Python 中的 lambda 是什么?
- 这是一个常被用于代码中的单个表达式的匿名函数。
- 所谓匿名,意即不再使用 def 语句这样标准的形式定义一个函数。
- lambda 只是一个表达式,函数体比 def 简单很多。
- lambda 的主体是一个表达式,而不是一个代码块。仅仅能在 lambda 表达式中封装有限的逻辑进去。
- lambda 函数拥有自己的命名空间,且不能访问自己参数列表之外或全局命名空间里的参数。
- 虽然 lambda 函数看起来只能写一行,却不等同于 C 或 C++ 的内联函数,后者的目的是调用小函数时不占用栈内存从而增加运行效率。
x = lambda a : a + 10
print(x(5)) # x(a)
15
# 可写函数说明
sum = lambda arg1, arg2: arg1 + arg2
# 调用sum函数
print ("相加后的值为 : ", sum( 10, 20 ))
print ("相加后的值为 : ", sum( 20, 20 ))
相加后的值为 : 30
相加后的值为 : 40
def myfunc(n):
return lambda a : a * n
mydoubler = myfunc(2)
mytripler = myfunc(3)
print(mydoubler(11))
print(mytripler(11))
22
33
- 为什么 lambda 没有语句?
- 匿名函数 lambda 没有语句的原因,是它被用于在代码被执行的时候构建新的函数对象并且
返回。
- Python 中的 pass 是什么?
- Pass 是一个在 Python 中不会被执行的语句。在复杂语句中,如果一个地方需要暂时被留白,它常常被用于占位符。
# 输出 Python 的每个字母
for letter in 'Python':
if letter == 'h':
pass
print ('这是 pass 块')
print ('当前字母 :', letter)
print ("END!")
当前字母 : P
当前字母 : y
当前字母 : t
这是 pass 块
当前字母 : h
当前字母 : o
当前字母 : n
END!
- pass 语句不会执行任何操作,一般作为占位符或者创建占位程序,如
while False:
pass
- Python 中什么是遍历器?
- 遍历器用于遍历一组元素,比如列表这样的容器。
- Python 中的 unittest 是什么?
- 在 Python 中,unittest 是 Python 中的单元测试框架。它拥有支持共享搭建、自动测试、在测试中暂停代码、将不同测试迭代成一组,等等的功能。
- unittest模块不像 doctest模块那么容易使用,不过它可以在一个独立的文件里提供一个更全面的测试集:
import unittest
class TestStatisticalFunctions(unittest.TestCase):
def test_average(self):
self.assertEqual(average([20, 30, 70]), 40.0)
self.assertEqual(round(average([1, 5, 7]), 1), 4.3)
self.assertRaises(ZeroDivisionError, average, [])
self.assertRaises(TypeError, average, 20, 30, 70)
unittest.main() # 从命令行调用将调用所有测试
E
======================================================================
ERROR: C:UsersTFXAppDataRoamingjupyterruntimekernel-1e1a7ebb-89d6-4e47-9989-8c6a327199db (unittest.loader._FailedTest)
----------------------------------------------------------------------
AttributeError: module '__main__' has no attribute 'C:UsersTFXAppDataRoamingjupyterruntimekernel-1e1a7ebb-89d6-4e47-9989-8c6a327199db'
----------------------------------------------------------------------
Ran 1 test in 0.001s
FAILED (errors=1)
An exception has occurred, use %tb to see the full traceback.
SystemExit: True
E:UsersTFXAnaconda3envstensorflow24libsite-packagesIPythoncoreinteractiveshell.py:3351: UserWarning: To exit: use 'exit', 'quit', or Ctrl-D.
warn("To exit: use 'exit', 'quit', or Ctrl-D.", stacklevel=1)
- 在 Python 中什么是 slicing?
- Slicing 是一种在有序的对象类型中(数组,元组,字符串)节选某一段的语法
- slice() 函数实现切片对象,主要用在切片操作函数里的参数传递。
myslice = slice(5) # 设置截取5个元素的切片
print(myslice)
arr = range(10)
print(arr)
print(arr[myslice])# 截取 5 个元素
slice(None, 5, None)
range(0, 10)
range(0, 5)
- 在 Python 中什么是构造器?
- 生成器是实现迭代器的一种机制。它功能的实现依赖于 yield 表达式,除此之外它跟普通的函数没有两样。
# 创建一个迭代器
class MyNumbers:
'''
__iter__() 方法返回一个特殊的迭代器对象, 这个迭代器对象实现了 __next__() 方法并通过 StopIteration 异常标识迭代的完成。
__next__() 方法(Python 2 里是 next())会返回下一个迭代器对象。
创建一个返回数字的迭代器,初始值为 1,逐步递增 1:
'''
def __iter__(self):
self.a = 1
return self
def __next__(self):
x = self.a
self.a += 1
return x
myclass = MyNumbers()
myiter = iter(myclass)
print(next(myiter))
print(next(myiter))
print(next(myiter))
print(next(myiter))
print(next(myiter))
1
2
3
4
5
class MyNumbers:
def __iter__(self):
self.a = 1
return self
def __next__(self):
if self.a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
- Python 中的 docstring 是什么?
- Python 中文档字符串被称为 docstring,它在 Python 中的作用是为函数、模块和类注释生成文档
- 如何在 Python 中拷贝一个对象?
- 赋值(=),就是创建了对象的一个新的引用,修改其中任意一个变量都会影响到另一个。
- 浅拷贝:创建一个新的对象,但它包含的是对原始对象中包含项的引用(如果用引用的方式修改其中一个对象,另外一个也会修改改变),例如,完全切片方法;工厂函数,如 list();copy 模块的 copy()函数。
- 深拷贝:创建一个新的对象,并且递归的复制它所包含的对象(修改其中一个,另外一个不会改变),例如,copy 模块的 deep.deepcopy()函数。
- 如果要在 Python 中拷贝一个对象,大多时候你可以用 copy.copy()或者 copy.deepcopy()。但并不是所有的对象都可以被拷贝。
import copy
a = [1,2,3]
b = a
c = a.copy()
d = copy.deepcopy(a)
print("id(a)",id(a))
print("id(b)",id(b))
print("id(c)",id(c))
print("id(d)",id(d))
id(a) 2594298381064
id(b) 2594298381064
id(c) 2594298155144
id(d) 2594298124040
- Python 中的负索引是什么?
- Python 中的序列索引可以是正也可以是负。如果是正索引,0 是序列中的第一个索引,1是第二个索引。如果是负索引,(-1)是最后一个索引而(-2)是倒数第二个索引。
- 如何将一个数字转换成一个字符串?
- 你可以使用自带函数 str()将一个数字转换为字符串。如果你想要八进制或者十六进制数,可以用 oct()或 hex()
num = 1
print(str(num))
print(oct(num))
print(hex(num))
1
0o1
0x1
- Xrange 和 range 的区别是什么?
- Xrange 用于返回一个 xrange 对象,而 range 用于返回一个数组。不管那个范围多大,Xrange 都使用同样的内存。
- xrange() 函数用法与 range 完全相同,所不同的是生成的不是一个数组,而是一个生成器。
- 注意:python3 取消了 xrange() 函数,并且和 range() 函数合并为 range()。
- Python 中的模块和包是什么?
- 在 Python 中,模块是搭建程序的一种方式。每一个 Python 代码文件都是一个模块,并可以引用其他的模块,比如对象和属性。一个包含许多 Python 代码的文件夹是一个包。一个包可以包含模块和子文件夹
- Python 是如何进行内存管理的?
- 从三个方面来说,一对象的引用计数机制,二垃圾回收机制,三内存池机制。
- 对象的引用计数机制
- Python 内部使用引用计数,来保持追踪内存中的对象,所有对象都有引用计数。
- 引用计数增加的情况:
- 一个对象分配一个新名称
- 将其放入一个容器中(如列表、元组或字典)
- 引用计数减少的情况:
- 使用 del 语句对对象别名显示的销毁
- 引用超出作用域或被重新赋值
- sys.getrefcount( )函数可以获得对象的当前引用计数
- 多数情况下,引用计数比你猜测得要大得多。对于不可变数据(如数字和字符串),解释器会在程序的不同部分共享内存,以便节约内存。
- 垃圾回收
- 当一个对象的引用计数归零时,它将被垃圾收集机制处理掉。
- 当两个对象 a 和 b 相互引用时,del 语句可以减少 a 和 b 的引用计数,并销毁用于引用底层对象的名称。然而由于每个对象都包含一个对其他对象的应用,因此引用计数不会归零,对象也不会销毁。(从而导致内存泄露)。
- 为解决这一问题,解释器会定期执行一个循环检测器,搜索不可访问对象的循环并删除它们。
- 内存池机制
- Python 提供了对内存的垃圾收集机制,但是它将不用的内存放到内存池而不是返回给操作系统。
- Pymalloc 机制。为了加速 Python 的执行效率,Python 引入了一个内存池机制,用于管理对小块内存的申请和释放。
- Python 中所有小于 256 个字节的对象都使用 pymalloc 实现的分配器,而大的对象则使用系统的 malloc。
- 对于 Python 对象,如整数,浮点数和 List,都有其独立的私有内存池,对象间不共享他们的内存池。也就是说如果你分配又释放了大量的整数,用于缓存这些整数的内存就不能再分配给浮点数。
- 什么是 lambda 函数?它有什么好处?
- lambda 表达式,通常是在需要一个函数,但是又不想费神去命名一个函数的场合下使用,也就是指匿名函数
- lambda 函数:首要用途是指点短小的回调函数
- lambda [arguments]:expression
a=lambda x,y:x+y
a(3,11)# lambda(3,11):3+11,此表达式只是为了方便说明,语法是错误的
14
- Python 里面如何实现 tuple 和 list 的转换?
- 直接使用 tuple 和 list 函数就行了,type()可以判断对象的类型
a = (1,2,3)
b = [1,2,3]
print(a,b)
print(list(a),tuple(b))
(1, 2, 3) [1, 2, 3]
[1, 2, 3] (1, 2, 3)
- Python 代码实现删除一个 list 里面的重复元
- 使用 set 集合函数,set(list),利用集合元素不重复的性质
a=[1,2,4,2,4,5,6,5,7,8,9,0,10,2,4,6]
set(a)
{0, 1, 2, 4, 5, 6, 7, 8, 9, 10}
- 使用字典函数,利用字典的关键字不重复的性质
a=[1,2,4,2,4,5,6,5,7,8,9,0,10,2,4,6]
b={}
b=b.fromkeys(a)
list(b.keys())
[1, 2, 4, 5, 6, 7, 8, 9, 0, 10]
- 用 sort 进行排序,然后从最后一个元素开始判断,去重
a=[1,2,4,2,4,5,6,5,7,8,9,0,10,2,4,6]
a.sort()
last=a[-1]
for i in range(len(a)-2,-1,-1):
if last==a[i]:
del a[i]
else:
last=a[i]
print(a)
[0, 1, 2, 4, 5, 6, 7, 8, 9, 10]
- except 的用法和作用?
- try…except…except…[else…][finally…]
- 执行 try 下的语句,如果引发异常,则执行过程会跳到 except 语句。对每个 except 分支顺序尝试执行,如果引发的异常与 except 中的异常组匹配,执行相应的语句。
- 如果所有的 except 都不匹配,则异常会传递到下一个调用本代码的最高层 try 代码中。
- try 下的语句正常执行,则执行 else 块代码。如果发生异常,就不会执行。
- 如果存在 finally 语句,最后总是会执行。
- range()函数的用法?
- 列出一组数据,经常用在 for in range()循环中
for i in range(10):
print(i,end=" ")
0 1 2 3 4 5 6 7 8 9
- 如何用 Python 来进行查询和替换一个文本字符串?
- 可以使用 re 模块中的 sub()函数或者 subn()函数来进行查询和替换,
- 格式:sub(replacement, string[,count=0])
- replacement 是被替换成的文本,string 是需要被替换的文本,count 是一个可选参数,指最大被替换的数量.
import re
p=re.compile('blue|white|red')
print(p.sub('colour','blue socks and red shoes'))
print(p.sub('colour','blue socks and red shoes',count=1))
colour socks and colour shoes
colour socks and red shoes
- subn()方法执行的效果跟 sub()一样,不过它会返回一个二维数组,包括替换后的新的字符串和总共替换的数量
import re
p=re.compile('blue|white|red')
print(p.subn('colour','blue socks and red shoes'))
print(p.subn('colour','blue socks and red shoes',count=1))
('colour socks and colour shoes', 2)
('colour socks and red shoes', 1)
- Python 里面 match()和 search()的区别?
- re 模块中 match(pattern,string[,flags]),检查 string 的开头是否与 pattern 匹配。
- re 模块中 re.search(pattern,string[,flags]),在 string 搜索 pattern 的第一个匹配值。
import re
print(re.match('super', 'superstition').span())
print(re.match('super', 'insuperable'))
print(re.search('super', 'superstition').span())
print(re.search('super', 'insuperable').span())
(0, 5)
None
(0, 5)
(2, 7)
- 用 Python 匹配 HTML tag 的时候,和有什么区别?
- 贪婪匹配( )和非贪婪匹配( )
import re
s = 'Title '
print(re.match('', s).group())
Title
import re
s = 'Title '
print(re.match('', s).group())
- Python 里面如何生成随机数?
- random 模块
- 随机整数:
- random.randint(a,b):返回随机整数 x,a
- random.randrange(start,stop,[,step]):返回一个范围在(start,stop,step)之间的随机整数,不包括结束值。
- 随机实数:
- random.random():返回 0 到 1 之间的浮点数
- random.uniform(a,b):返回指定范围内的浮点数。
import random
random.randint(0,10)
10
random.randrange(0,10,2)
2
random.random()
0.3569320956561295
random.uniform(0,1)
0.5371507256725325
- 有没有一个工具可以帮助查找 python 的 bug 和进行静态的代码分析?
- PyChecker 是一个 python 代码的静态分析工具,它可以帮助查找 python 代码的 bug, 会对代码的复杂度和格式提出警告
- Pylint 是另外一个工具可以进行 codingstandard 检查。
- 如何在一个 function 里面设置一个全局的变量?
- 解决方法是在 function 的开始插入一个 global 声明:
def f():
global a
- 单引号,双引号,三引号的区别
- 单引号和双引号是等效的,如果要换行,需要符号(),三引号则可以直接换行,并且可以包含注释,
- 如果要表示 Let’s go 这个字符串,
- 单引号:s = ‘Let’s go’
- 双引号:s = “Let’s go”
- s = ‘I realy like “python”!’
s1 = 'Let's go'
s2 = "Let's go"
s3 = 'I realy like "python"!'
print(s1,'|',s2,'|',s3)
Let's go | Let's go | I realy like "python"!
- __init__和__new__的区别?
- __init__在对象创建后,对对象进行初始化,只负责初始化。
- __new__是在对象创建之前创建一个对象,并将该对象返回给__init__,只负责创建。
注:自定义 new() 方法一般并不常用,而且容易与 init() 相混淆。实际上这两个方法也确实相似,比如他们都是在创建类的实例时会被默认调用的方法,而且创建实例时传入的参数也都会传到这两个方法里。但他们也有很重要的区别,比如对 new() 的调用比 init() 要早,new() 有返回值,init() 没有。
真正完成构造实例工作的是 new() 方法,调用它需要一个默认参数 cls,就是将要返回的这个实例所属的类(MyClass)。一般情况下因为 new() 极少被覆盖,最终调用的都是 object.new()。这个时候我们的实例已经被创建了,就可以当做 self 参数传给 init() 了,init() 做的工作其实仅是初始化一些属性值之类的,与严格意义下的“构造”实例无关。
class Myclass(object):# 创建一个音乐播放器
def __init__(self): # 初始化方法;对这个实例化对象再次加工
print("初始化")
def __new__(cls):
print("创建对象,分配空间") # 创建对象时,new方法会被自动调
instance = super().__new__(cls) # 为对象分配空间
# 创建对象
my = Myclass()
print(my)
创建对象,分配空间
None
class Myclass(object):# 创建一个音乐播放器
def __init__(self): # 初始化方法;对这个实例化对象再次加工
print("初始化")
def __new__(cls):
print("创建对象,分配空间") # 创建对象时,new方法会被自动调
instance = super().__new__(cls) # 为对象分配空间
return instance # 返回对象的引用,必须的有这个返回,不然self找不到对象
# 创建对象
my = Myclass()
print(my)
创建对象,分配空间
初始化
注:
- self:self代表自身的意思,就是代表这个类对象自身的意思不代表类本身,创建对象后self就代表这个对象自身。
- cls:cls代表这个类,这个类的所有属性、方法都在里面。
class SeftAndCls(object):# class(父类)
a = 'a'
@staticmethod # 静态方法(装饰器)
def f1():
return SeftAndCls.a # 正常
def f2(self):
return 'f2'
@classmethod # 类方法(装饰器)
def f3(cls, name):
print('f3函数输出:')
print('类.类属性调用一个类属性:',SeftAndCls.a) # 使用类.类属性调用一个类属性
print('类.类方法调用一个类方法:',cls().f2()) # 使用类.类方法调用一个类方法
newobj = SeftAndCls()
print('调用类的静态方法:', SeftAndCls.f1())
print('正常调用:', newobj.f2())
print('直接调用类属性', SeftAndCls.a)
SeftAndCls.f3('World')
调用类的静态方法: a
正常调用: f2
直接调用类属性 a
f3函数输出:
类.类属性调用一个类属性: a
类.类方法调用一个类方法: f2
参考链接
- Python-百度百科
- Python官网
- Python3 菜鸟教程
- https://github.com/jackfrued/Python-Interview-Bible
- https://github.com/taizilongxu/interview_python
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
机房租用,北京机房租用,IDC机房托管, http://www.fwqtg.net