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 中的字符串编码

  1. ASCII (American Standard Code for Information Interchange):

    • 最早的字符编码标准,使用7位二进制数表示128个字符,包括英文大小写字母、数字和一些特殊符号。
    • 由于只支持英文字符,因此不适合表示其他语言。
  2. Unicode:

    • 为了解决ASCII编码的局限性,Unicode提供了一种可以表示世界上几乎所有文字的字符集。
  3. 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:一个布尔表达式,其结果为TrueFalse
  • 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装饰器定义。
  • 它们不需要selfcls作为第一个参数,这意味着它们不能访问类或实例的属性。
  • 静态方法可以看作是类内部的普通函数,它们仅在需要时通过类来调用。
class MyClass:
    @staticmethod
    def static_method():
        print("这是静态方法,可以通过类或实例调用")

# 通过类调用
MyClass.static_method()  # 输出: 这是静态方法,可以通过类或实例调用

# 通过实例调用
obj = MyClass()
obj.static_method()  # 同样输出: 这是静态方法,可以通过类或实例调用

4.反射

反射(Reflection)是指程序在运行时(Runtime)能够查询和修改自身的属性和方法。

  1. getattr():

    • 根据属性名获取对象的属性值。
    class MyClass:
        def __init__(self):
            self.x = 5
    
    obj = MyClass()
    print(getattr(obj, 'x'))  # 输出: 5
    
  2. setattr():

    • 设置对象的属性值。
    obj = MyClass()
    setattr(obj, 'y', 10)
    print(getattr(obj, 'y'))  # 输出: 10
    
  3. 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.格式化

  1. %操作符

使用%操作符,你可以将值插入到字符串中。这种方法是老版本的Python中常用的格式化方式。

name = "Alice"
age = 30
print("Name: %s, Age: %d" % (name, age))
# 输出: Name: Alice, Age: 30
print("Pi: %.2f" % 3.1415926)  
# 输出: Pi: 3.14
  1. 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
  1. 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.正则表达式

  1. 字符:正则表达式中的普通字符(例如,字母、数字、标点符号)匹配自身。
  2. 量词:
    • *:匹配前面的字符零次或多次。
    • +:匹配前面的字符一次或多次。
    • ?:匹配前面的字符零次或一次。
    • {n}:匹配确定的n次。
    • {n,}:至少匹配n次。
    • {n,m}:最少匹配n次,最多匹配m次。
  3. 字符类:
    • [abc]:匹配任何一个字符(a、b或c)。
    • [^abc]:匹配任何不是字符类中列出的字符。
    • .:匹配任何单个字符(除了换行符)。
  4. 锚点:
    • ^:匹配字符串的开始位置。
    • $:匹配字符串的结束位置。
  5. 分组:
    • ():将多个表达式组合成一个子表达式,并捕获匹配的文本。
  6. 选择:
    • |:逻辑“或”,匹配两个表达式中的任意一个。
  7. 否定:
    • ^(在字符类中):匹配任何不在字符类中的字符。
    • \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()
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐