Python
基本概念
1. Python是解释型语言还是编译型语言
是解释型。解释型是边编译边执行。编译型语言是把源程序全部编译成二进制的可运行程序后再运行,如C/C++ 。
注:java程序不是直接编译成机器语言,而是编译成字节码,然后用解释方式执行字节码。
2. Python是面向对象语言还是面向过程语言
是面向对象。面向对象编程(OOP)的特点包括:
- 封装:将数据和操作这些数据的方法组合在一起。
- 继承:允许新创建的类(子类)继承现有类(父类)的属性和方法。
- 多态:允许不同类的对象对同一消息做出响应,但具体的行为会根据对象的实际类型而有所不同。
面向过程编程的特点包括:
- 将程序分解为一系列的过程或函数,每个过程或函数执行特定的任务。
- 强调过程和函数的调用,而不是对象和类。
3. Python基本数据类型
- Numbers(数字):3.7以后存储字节数会根据数字大小变化(28+48(num/230))
- List(列表):有序集合。多维列表本质就是列表里面叠列表
- Tuple(元组):有序集合。元组是只读的列表
- Dictionary(字典):无序集合,由键值对(key-value)组成。
- 集合(set):是一组 key 的集合,每个元素都是唯一,不重复且无序的。
- a=(4),a的类型为整数
4.append和 extend区别
-
append()方法用于将一个对象添加到列表的末尾。当使用append()方法添加一个列表到另一个列表时,实际上是将整个列表作为一个单独的元素添加到原列表中。
-
extend()方法用于将一个可迭代对象(如列表、元组、字符串等)的所有元素添加到列表的末尾。使用extend()方法添加一个列表到另一个列表时,实际上是将这个列表中的所有元素逐个添加到原列表中。
my_list = [1, 2, 3]
my_list.extend([4, 5]) # 结果: [1, 2, 3, 4, 5]
my_list.append([5, 6]) # 结果: [1, 2, 3, 4, [5, 6]]
5.del、pop和remove区别
del
:根据下标进行删除pop
:根据下标进行删除并返回删除值,默认删除最后一个元素remove
:根据元素的值进行删除
my_list = [1, 2, 3, 4, 5]
del my_list[2] # my_list: [1, 2, 4, 5]
a=my_list.pop(0) # my_list: [2, 4, 5], a: 0
my_list.remove(4) # my_list: [2, 5]
6. sort和sorted区别
- sorted()是一个内置函数,不会修改原始的序列,而是返回一个新的排序后的列表。不会修改原始的序列,而是返回一个新的排序后的列表。
- sort()是列表(list)的一个方法,它直接修改原列表,按照指定的顺序对列表中的元素进行排序。
my_list = [3, 1, 4, 1, 5]
my_list.sort()
print(my_list) # 输出: [1, 1, 3, 4, 5]
sorted_list = sorted(my_list, reverse=True) # 设置reverse为True进行降序排序
print(my_list) # 输出: [1, 1, 3, 4, 5]
print(sorted_list) # 输出: [5, 4, 3, 1, 1]
reverse和reversed同理
my_list = [1, 2, 3, 4, 5]
reversed_iterator = reversed(my_list)
print(list(reversed_iterator)) # 输出: [5, 4, 3, 2, 1]
print(my_list) # 原始列表未被修改: [1, 2, 3, 4, 5]
my_list.reverse()
print(my_list) # 输出: [5, 4, 3, 2, 1]
7.介绍一下Python 中的字符串编码
-
ASCII (American Standard Code for Information Interchange):
- 最早的字符编码标准,使用7位二进制数表示128个字符,包括英文大小写字母、数字和一些特殊符号。
- 由于只支持英文字符,因此不适合表示其他语言。
-
Unicode:
- 为了解决ASCII编码的局限性,Unicode提供了一种可以表示世界上几乎所有文字的字符集。
-
UTF-8 (8-bit Unicode Transformation Format):
-
是Unicode的一种实现方式,可以根据字符的不同使用不同长度(1-4)的字节来表示一个字符。
-
UTF-8最大的特点是它对ASCII编码是兼容的,即ASCII字符在UTF-8中用一个字节表示,与ASCII编码相同。
-
str.encode()
: 将字符串编码为指定格式的字节串。bytes.decode()
: 将字节串解码为字符串。
8.is 和 == 的区别
==
是比较操作符,只是判断对象的值(value)是否一致,而 is
则判断的是对象之间的身份(内存地址)是否一致。
对象的身份,可以通过
id()
方法来查看。
9.三元运算
a if condition else b
a
:当条件condition
为真(True
)时返回的值。condition
:一个布尔表达式,其结果为True
或False
。b
:当条件condition
为假(False
)时返回的值。
进阶
1.shuffle
random.shuffle
用于将序列(如列表)中的元素随机打乱位置。它就地修改传入的序列,不返回任何值。
import random
list_items = [1, 2, 3, 4, 5]
random.shuffle(list_items)
print(list_items) # 输出可能是: [3, 5, 1, 2, 4]
2. 如何判断是函数还是方法
- 与类和实例无绑定关系的
function
都属于函数(function) - 与类和实例有绑定关系的
function
都属于方法(method)
3. 方法
方法可以分为三种类型:实例方法、类方法和静态方法。
- 实例方法:依赖于实例的状态,通常用于定义对象的行为。
- 类方法:依赖于类的状态,通常用于定义与类相关的行为或工厂方法。
- 静态方法:不依赖于类或实例的状态,通常用于工具函数或不需要访问类或实例数据的方法。
实例方法(Instance Methods)
- 实例方法是最常见的方法类型,它们需要一个
self
参数作为第一个参数,代表类的实例本身。 - 实例方法可以访问和修改实例的状态(属性)。
- 它们通常用于定义对象的行为。
class MyClass:
def instance_method(self):
print("这是实例方法,可以通过实例调用")
obj = MyClass()
obj.instance_method() # 输出: 这是实例方法,可以通过实例调用
类方法(Class Methods)
- 类方法是与类相关联的方法,使用
@classmethod
装饰器定义。 - 它们需要一个
cls
参数作为第一个参数,代表类本身。 - 类方法可以访问和修改类的状态(类属性),但不能访问实例的状态。
- 它们常用于工厂方法,即根据参数创建类的实例。
class MyClass:
@classmethod
def class_method(cls):
print("这是类方法,可以通过类或实例调用")
# 通过类调用
MyClass.class_method() # 输出: 这是类方法,可以通过类或实例调用
# 通过实例调用
obj = MyClass()
obj.class_method() # 同样输出: 这是类方法,可以通过类或实例调用
静态方法(Static Methods)
- 静态方法是不涉及类或实例数据的方法,使用
@staticmethod
装饰器定义。 - 它们不需要
self
或cls
作为第一个参数,这意味着它们不能访问类或实例的属性。 - 静态方法可以看作是类内部的普通函数,它们仅在需要时通过类来调用。
class MyClass:
@staticmethod
def static_method():
print("这是静态方法,可以通过类或实例调用")
# 通过类调用
MyClass.static_method() # 输出: 这是静态方法,可以通过类或实例调用
# 通过实例调用
obj = MyClass()
obj.static_method() # 同样输出: 这是静态方法,可以通过类或实例调用
4.反射
反射(Reflection)是指程序在运行时(Runtime)能够查询和修改自身的属性和方法。
-
getattr()
:- 根据属性名获取对象的属性值。
class MyClass: def __init__(self): self.x = 5 obj = MyClass() print(getattr(obj, 'x')) # 输出: 5
-
setattr()
:- 设置对象的属性值。
obj = MyClass() setattr(obj, 'y', 10) print(getattr(obj, 'y')) # 输出: 10
-
hasattr()
:- 检查对象是否具有指定的属性或方法。
obj = MyClass() print(hasattr(obj, 'x')) # 输出: True
5.元类
元类(Metaclass)是创建类的一种方式,它被称为“类的类”。元类定义了类的创建方式和行为。
class Meta(type):
def __new__(cls, name, bases, class_dict):
# 可以在这里修改class_dict
print(f"Creating class {name}")
return super().__new__(cls, name, bases, class_dict)
class MyClass(metaclass=Meta):
pass
# 输出:Creating class MyClass
6.闭包
闭包(Closure)是函数式编程中的一个概念,它指的是一个函数能够记住其创建环境中的变量,即使该环境的执行已经结束。闭包通常由嵌套函数创建,并且能够访问外部函数的非全局变量。
- 能够访问外部作用域中的变量:闭包可以访问创建它的外部函数中定义的变量。
- 保持这些变量的绑定:即使外部函数已经执行完毕,闭包仍然能够访问和操作这些变量。
- 延迟计算:闭包可以推迟对某些变量的计算,直到实际需要它们的时候。
def num():
return [lambda x:i*x for i in range(4)]
[m(1) for m in num()] # 输出: [3, 3, 3, 3]
7.装饰器
装饰器(Decorator)本质上是一个函数,它接受一个函数作为参数,并返回一个新的函数。用于在不修改原有函数代码的基础上增加函数的新功能。
def my_decorator(func):
def wrapper():
print("Something before")
func()
print("Something after")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello()
# 输出:
# Something before
# Hello!
# Something after
8.isinstance
type()
不会认为子类是一种父类类型,不考虑继承关系;isinstance()
会认为子类是一种父类类型,考虑继承关系。
9.格式化
- %操作符
使用%
操作符,你可以将值插入到字符串中。这种方法是老版本的Python中常用的格式化方式。
name = "Alice"
age = 30
print("Name: %s, Age: %d" % (name, age))
# 输出: Name: Alice, Age: 30
print("Pi: %.2f" % 3.1415926)
# 输出: Pi: 3.14
str.format()
方法
str.format()
方法提供了一个更现代且灵活的字符串格式化方式。你可以在字符串中使用花括号{}
作为占位符,然后调用format()
方法传入相应的值。
name = "Alice"
age = 30
print("Name: {}, Age: {}".format(name, age))
# 输出: Name: Alice, Age: 30
# 也可以指定位置和格式
print("Name: {0}, Age: {1}".format(name, age))
print("Name: {1}, Age: {0}".format(age, name))
print("Pi: {:.2f}".format(3.1415926))
# 输出: Pi: 3.14
- f-string(格式化字符串字面量)
Python 3.6+ 引入了f-string,提供了一种非常简洁和易读的方式来格式化字符串。在字符串前加上字母f
,然后直接在花括号{}
中写入变量名或表达式。
name = "Alice"
age = 30
print(f"Name: {name}, Age: {age}")
# 输出: Name: Alice, Age: 30
# 直接在字符串中进行表达式计算
print(f"Age squared: {age**2}")
10.浅拷贝(Shallow Copy)&深拷贝(Deep Copy)
- 浅拷贝复制的是原始对象中包含的引用,而不是对象本身。
- 深拷贝递归地复制了原始对象中的所有对象。这意味着深拷贝会创建原始对象的完整副本,包括所有嵌套的对象,修改原始对象不会影响深拷贝。
import copy
original_list = [[1, 2, 3], [4, 5, 6]]
shallow_copied_list = copy.copy(original_list)
# 浅拷贝
original_list[0][0] = 'X'
print(shallow_copied_list) # 输出: [['X', 2, 3], [4, 5, 6]]
# 深拷贝
deep_copied_list = copy.deepcopy(original_list)
original_list[0][0] = 'X'
print(deep_copied_list) # 输出: [[1, 2, 3], [4, 5, 6]]
11.lambda
lambda是一个用于创建匿名函数的关键字。匿名函数是一种没有名称的函数,它们通常用于需要函数对象的地方,但又不想去定义一个完整的函数。
people = [("Alice", 30), ("Bob", 25), ("Charlie", 35)]
sorted_people = sorted(people, key=lambda person: person[1])
print(sorted_people) # 输出: [('Bob', 25), ('Alice', 30), ('Charlie', 35)]
12.规约函数reduce
reduce(function, iterable, initializer=None)
function
:二元操作函数,接受两个参数。应用于iterable
的元素。iterable
:要累积的序列或可迭代对象。initializer
(可选):指定累积的初始值。默认无。
function函数先对集合中的第 1、2 个元素进行操作,得到的结果再与后续数值运算,最后得到一个结果。
13. __new__ 和 __init__区别
__new__
负责创建对象,__init__
负责初始化对象。__new__
是一个静态方法,__init__
是一个实例方法。__new__
必须返回一个实例,__init__
不返回任何值。__new__
在__init__
之前被调用。
14. *arg 和**kwarg作用
-
*args
代表可变数量的位置参数(arguments),它允许你将不定数量的位置参数传递给函数。这些参数被组织为一个元组(tuple),在函数内部可以通过索引来访问。 -
**kwargs
代表可变数量的关键字参数(keyword arguments),它允许你将不定数量的关键字参数传递给函数。这些参数被组织为一个字典(dictionary),在函数内部可以通过键来访问。
def my_function(*args, **kwargs):
for arg in args:
print(arg)
for key, value in kwargs.items():
print(f"{key}: {value}")
my_function(1, 2, name="Alice", age=25)
# 输出: 1, 2, name: Alice, age: 25
15.yield
yield
是一个关键字,用于在函数中定义一个生成器(generator)。生成器是一种特殊的迭代器,它允许你逐个产生值,而不是一次性计算并存储所有值。使用yield
可以暂停函数的执行,保留当前函数的状态,并在下一次迭代时从它离开的地方继续执行。
def fibonacci(n):
a, b = 0, 1
for _ in range(n):
yield a
a, b = b, a + b
# 使用生成器
fib = fibonacci(10)
for num in fib:
print(num)
# 输出斐波那契数列的前10个数
16. zip
将多个可迭代对象(如列表、元组、字符串等)中对应的元素打包成一个个元组,然后返回由这些元组组成的迭代器
# 列表
list1 = [1, 2, 3]
list2 = ['a', 'b', 'c']
# 使用zip函数
zipped = zip(list1, list2)
# 将zip对象转换为列表查看结果
print(list(zipped))
# 输出: [(1, 'a'), (2, 'b'), (3, 'c')]
17.排序
18.正则表达式
- 字符:正则表达式中的普通字符(例如,字母、数字、标点符号)匹配自身。
- 量词:
*
:匹配前面的字符零次或多次。+
:匹配前面的字符一次或多次。?
:匹配前面的字符零次或一次。{n}
:匹配确定的n次。{n,}
:至少匹配n次。{n,m}
:最少匹配n次,最多匹配m次。
- 字符类:
[abc]
:匹配任何一个字符(a、b或c)。[^abc]
:匹配任何不是字符类中列出的字符。.
:匹配任何单个字符(除了换行符)。
- 锚点:
^
:匹配字符串的开始位置。$
:匹配字符串的结束位置。
- 分组:
()
:将多个表达式组合成一个子表达式,并捕获匹配的文本。
- 选择:
|
:逻辑“或”,匹配两个表达式中的任意一个。
- 否定:
^
(在字符类中):匹配任何不在字符类中的字符。\b
:匹配单词边界。\B
:匹配非单词边界。
Python通过re
模块提供对正则表达式的支持。以下是一些常用的函数:
re.match()
:从字符串的开始位置匹配一个模式。re.search()
:扫描整个字符串,寻找第一个位置的匹配。re.findall()
:找出字符串中所有匹配的模式。re.finditer()
:返回一个迭代器,每次迭代返回一个match对象。re.sub()
:替换字符串中的匹配项。re.split()
:根据匹配的模式分割字符串。
19.猴子补丁
猴子补丁(Monkey Patching)是一种在运行时动态地修改或扩展代码的行为。
class MyClass:
def my_method(self):
print("Original method")
# 直接修改方法
def new_method(self):
print("New method")
MyClass.my_method = new_method
obj = MyClass()
obj.my_method() # 输出: New method
20.assert
在Python中,assert
是一个内置的关键字,用于断言某个条件是真的。如果条件为真,则程序继续执行;如果条件为假,则程序抛出AssertionError
异常。assert
通常用于调试阶段,确保代码中的某些条件一定为真,从而避免潜在的错误。
-
assert
的基本语法如下:条件
:一个布尔表达式,必须为真。"可选的错误信息"
:如果省略,当断言失败时,默认的错误信息是AssertionError
;如果提供,将显示该错误信息。
-
assert
语句不会影响程序的逻辑,它们仅用于调试目的。在生产环境中,通常应该避免使用assert
。 -
可以通过Python解释器的
-O
(优化)选项关闭assert
语句。在优化模式下,所有的assert
语句都会被忽略,不会执行。
# 1
def divide(a, b):
assert b != 0, "除数不能为0"
return a / b
divide(10, 0) # 抛出 AssertionError: 除数不能为0
# 2
def add(a, b):
assert isinstance(a, (int, float)) and isinstance(b, (int, float)), "参数必须是数字"
return a + b
add("10", 5) # 抛出 AssertionError: 参数必须是数字
def test_add():
assert add(1, 2) == 3, "1 + 2 应该等于 3"
assert add(-1, 1) == 0, "(-1) + 1 应该等于 0"
test_add()