什么网站可以做软件有哪些东西吗,典型的c2c平台有哪些,app渠道推广,做网站时如何去掉网站横条1. 可变对象和不可变对象
(1). 不可变对象#xff08; Immutable Objects #xff09;
不可变对象指的是那些一旦创建后其内容就不能被修改的对象。如果尝试修改不可变对象的内容#xff0c;将会创建一个新的对象而不是修改原来的对象。常见的不可变类型包括#xff1a; …1. 可变对象和不可变对象
(1). 不可变对象 Immutable Objects
不可变对象指的是那些一旦创建后其内容就不能被修改的对象。如果尝试修改不可变对象的内容将会创建一个新的对象而不是修改原来的对象。常见的不可变类型包括
数字类型 int, float, complex 字符串 str 元组 tuple 冻结集合 frozenset
可以理解为对象的内容一旦修改(改变)对象的内存地址改变
s Hello
print(id(s)) # 输出原始字符串的内存地址s , World!
print(id(s)) # 输出新字符串的内存地址与之前不同(2). 可变对象
可变对象是指在其创建之后还可以对其内容进行修改的对象。这意味着你可以在不改变对象身份的情况下更改它的内容。常见的可变类型包括
列表 list 字典 dict 集合 set **自定义类实例**除非特别设计为不可变
lst [1, 2, 3]
print(id(lst)) # 输出列表的内存地址
lst.append(4)
print(id(lst)) # 内存地址保持不变说明是原地修改2. staticmethod和classmethod
(1). staticmethod
定义使用staticmethod装饰的方法不接受隐式的第一个参数如self或cls。这意味着这些方法既不能访问实例属性也不能访问类属性。
用途通常用于那些与类有关但不需要访问类或实例内部数据的功能。 这样的方法更像是普通的函数只是由于组织上的原因被放在了类中。
特点
不能访问实例属性 由于静态方法没有self参数所以无法访问任何与特定对象实例相关的属性。不能访问类属性 同样地因为没有cls参数静态方法也无法直接访问类级别的属性。
class Example:class_var I am a class variable # 类变量def __init__(self, value):self.instance_var value # 实例变量staticmethoddef static_method():# 下面这两行会导致错误因为静态方法无法访问实例或类属性# print(self.instance_var) # AttributeError: staticmethod object has no attribute instance_var# print(class_var) # NameError: name class_var is not definedprint(This is a static method.)def instance_method(self):print(fInstance variable: {self.instance_var})print(fClass variable: {Example.class_var})# 创建实例
ex Example(I am an instance variable)# 调用静态方法
Example.static_method() # 输出: This is a static method.# 调用实例方法
ex.instance_method()
# 输出:
# Instance variable: I am an instance variable
# Class variable: I am a class variable在这个例子中my_static_method是一个静态方法它可以直接通过类名调用不需要创建类的实例。
(2). classmethod
定义 使用classmethod装饰的方法接收一个隐含的第一个参数这个参数通常是cls代表类本身。因此类方法可以访问和修改类级别的属性也可以调用其他类方法。
用途 常用于需要操作类级别数据的方法或者当你需要从该方法返回类的不同子类时很有用。
示例 1: 访问和修改类级别属性
假设我们有一个Person类其中包含一个类级别的属性count用于记录创建了多少个Person对象。我们可以使用类方法来更新这个计数器。
class Person:count 0 # 类变量用于跟踪创建了多少个Person对象def __init__(self, name):self.name namePerson.count 1 # 每当创建一个新的实例时增加计数classmethoddef get_count(cls):return cls.count # 使用cls访问类变量# 创建一些Person实例
p1 Person(Alice)
p2 Person(Bob)
# 使用类方法获取当前的计数
print(Person.get_count()) # 输出应该是2因为创建了两个实例在这个例子中get_count是一个类方法它可以通过cls访问类级别的属性count而无需实例化Person类。
示例 2: 提供替代构造函数
有时候你可能希望提供多种方式来创建类的实例。你可以利用类方法作为“工厂方法”为不同的需求提供不同的构造逻辑。
class Date:def __init__(self, year, month, day):self.year yearself.month monthself.day dayclassmethoddef from_string(cls, date_string):year, month, day map(int, date_string.split(-))return cls(year, month, day) # 返回一个新实例# 使用标准构造函数
date1 Date(2023, 4, 1)# 使用类方法提供的替代构造函数
date2 Date.from_string(2023-04-01)print(date1.year, date1.month, date1.day) # 输出2023 4 1
print(date2.year, date2.month, date2.day) # 输出2023 4 1这里from_string类方法允许用户从字符串格式的数据创建Date对象这增加了灵活性。
示例 3: 调用其他类方法
类方法还可以调用其他的类方法或静态方法这在需要链式操作或者复用已有逻辑的情况下非常有用。
class MathOperations:classmethoddef add(cls, a, b):return a bclassmethoddef multiply(cls, a, b):return a * bclassmethoddef combined_operation(cls, a, b):sum_result cls.add(a, b)product_result cls.multiply(a, b)return sum_result, product_resultresult MathOperations.combined_operation(5, 3)
print(result) # 输出(8, 15)分别是加法和乘法的结果在上面的例子中combined_operation类方法内部调用了另外两个类方法add和multiply来完成一系列计算。
3. 迭代器和生成器
(1) 迭代器Iterator
迭代器是一个可以记住遍历位置的对象它从集合的第一个元素开始访问直到所有的元素被访问完结束。迭代器只能往前不会后退。 在Python中要创建一个迭代器对象需要实现两个方法__iter__() 和 __next__()
(1.1) 内置迭代器
序列迭代器 列表、元组、字符串等序列类型都有默认的迭代器。
my_list [1, 2, 3]
iterator iter(my_list)
print(next(iterator)) # 输出: 1字典视图迭代器 如 .keys(), .values(), .items()返回的都是迭代器对象。
python
深色版本
my_dict {a: 1, b: 2}
keys_iterator iter(my_dict.keys())
print(next(keys_iterator)) # 输出: a文件迭代器 打开的文件对象也是迭代器可用于逐行读取文件内容。
with open(example.txt, r) as file:for line in file:print(line.strip())(1.2) 自定义迭代器
iter()返回迭代器对象本身。next()返回容器中的下一个值。如果没有更多的元素可供返回则抛出 StopIteration 异常。 迭代器的一个重要特性是可以节省内存因为它不需要一次性加载整个数据集到内存中而是按需生成数据。
class MyIterator:def __init__(self, max_value):self.max_value max_valueself.current 0def __iter__(self):return selfdef __next__(self):if self.current self.max_value:value self.currentself.current 1return valueelse:raise StopIteration# 使用自定义迭代器
my_iter MyIterator(3)
for i in my_iter:print(i) # 输出: 0, 1, 2(2) 生成器Generator
(2.1) 生成器函数
生成器是一种特殊的迭代器它是通过函数来创建的但是与普通函数不同的是生成器使用了 yield 关键字而不是 return。每当生成器函数执行到 yield 语句时它会暂停并保存当前的所有状态然后返回 yield 的值给调用者。当后续再次调用生成器时它会从上次离开的地方继续执行 。这种机制使得生成器非常适合处理大数据集或惰性计算lazy evaluation因为它不需要一次性加载所有数据到内存中。
yield 与 return 的区别:
return一 旦执行了 return 语句函数就会结束并且所有的局部变量都会被销毁。 yield 每当执行到 yield 语句时函数会暂停并返回一个值给调用者但是函数的状态会被保存下来下次调用时可以从上次暂停的地方继续执行。
def generator(n):for i in range(n):print(before yield)yield iprint(after yield)gen generator(3)print(next(gen)) # 第一次调用next
print(---)# 使用for循环遍历剩余的元素 自动调用__next__
# 第二、第三次都是在这个下面调用并打印
for i in gen: print(i)完整输出结果
before yield
0
---
after yield
before yield
1
after yield
before yield
2
after yield(2.2) 生成器表达式
生成器表达式提供了一种简洁的方式来创建生成器类似于列表推导式的语法但使用圆括号 () 而不是方括号 [] 。与列表推导式不同的是生成器表达式不会一次性生成所有元素并存储在内存中而是按需生成每个元素。
gen_exp (x*x for x in range(5))
print(next(gen_exp)) # 输出: 0
print(next(gen_exp)) # 输出: 1
print(next(gen_exp)) # 输出: 4
# 继续打印剩余的平方数...4. 装饰器
Python 装饰器Decorator是一种用于修改函数或方法行为的高级特性。它本质上是一个返回函数的函数通常用于在不改变原函数定义的情况下为函数添加新的功能。装饰器广泛应用于日志记录、访问控制、性能测量等场景。
4.1 基本概念
装饰器的基本语法是使用 decorator_name 语法语法糖Syntactic Sugar将装饰器应用到一个函数或方法上。例如
my_decorator
def my_function():print(执行函数)这相当于下面的代码
def my_function():print(执行函数)
my_function my_decorator(my_function)简单示例
以下是一个简单的装饰器示例该装饰器会在调用函数前后打印消息
def simple_decorator(func):def wrapper():print(函数之前的操作)func()print(函数之后的操作)return wrappersimple_decorator
def say_hello():print(Hello!)say_hello()输出结果将是
函数之前的操作
Hello!
函数之后的操作4.2 带参数的装饰器
如果需要装饰的函数带有参数可以通过在 wrapper 函数中使用 *args 和 **kwargs 来处理任意数量的位置参数和关键字参数
def decorator_with_arguments(func):def wrapper(*args, **kwargs):print(函数之前的操作)result func(*args, **kwargs)print(函数之后的操作)return resultreturn wrapperdecorator_with_arguments
def greet(name):print(fHello, {name}!)greet(Alice)输出结果将是
函数之前的操作
Hello, Alice!
函数之后的操作4.3 带参数的装饰器工厂
有时你可能希望装饰器本身也接受参数。这时可以创建一个装饰器工厂即一个返回装饰器的函数
def repeat(num_times):def decorator_repeat(func):def wrapper(*args, **kwargs):for _ in range(num_times):result func(*args, **kwargs)return resultreturn wrapperreturn decorator_repeatrepeat(3)
def say_hello():print(Hello!)say_hello()这段代码会让 say_hello 函数执行三次。
4.4 类装饰器
除了函数装饰器外还可以使用类作为装饰器。为此你需要实现 __call__() 方法使得类实例可调用
class ClassDecorator:def __init__(self, func):self.func funcdef __call__(self, *args, **kwargs):print(函数之前的操作)result self.func(*args, **kwargs)print(函数之后的操作)return resultClassDecorator
def say_goodbye():print(Goodbye!)say_goodbye()5. 深拷贝和浅拷贝
5.1 浅拷贝Shallow Copy
浅拷贝创建一个新的对象但不递归地复制嵌套的对象。换句话说原对象和新对象共享嵌套对象的引用。
特点
创建一个新对象。新对象包含对原始对象中元素的引用而不是这些元素的副本。如果原始对象中的元素是可变对象如列表、字典则新旧对象共享这些可变对象。
import copyoriginal_list [[1, 2], [3, 4]]
shallow_copied_list copy.copy(original_list)# 修改浅拷贝中的一个子列表
shallow_copied_list[0][0] Xprint(Original List:, original_list) # 输出: Original List: [[X, 2], [3, 4]]
print(Shallow Copied List:, shallow_copied_list) # 输出: Shallow Copied List: [[X, 2], [3, 4]]可以看到修改浅拷贝中的子列表也影响了原始列表因为它们共享相同的子列表对象。
5.2 深拷贝Deep Copy
深拷贝不仅创建一个新的对象还会递归地复制所有嵌套的对象。这意味着新对象和原始对象完全独立没有任何共享的引用。
特点
创建一个新对象。新对象包含原始对象中所有元素的副本包括嵌套对象的所有层级。原始对象和新对象之间没有共享的引用。
import copyoriginal_list [[1, 2], [3, 4]]
deep_copied_list copy.deepcopy(original_list)# 修改深拷贝中的一个子列表
deep_copied_list[0][0] Xprint(Original List:, original_list) # 输出: Original List: [[1, 2], [3, 4]]
print(Deep Copied List:, deep_copied_list) # 输出: Deep Copied List: [[X, 2], [3, 4]]6 lambda函数
lambda 函数的基本语法如下
lambda 参数1, 参数2, ... : 表达式参数可以有多个参数用逗号分隔。表达式 是一个单一的表达式而不是一个代码块。lambda 函数会返回该表达式的值。快速理解 lambda 函数的一个有效方法是明确其输入参数和输出表达式的结果。你可以将 lambda 函数视为一个简单的函数定义并且只关注它的输入和输出。
示例
6.1 无参数的 lambda 函数
f lambda: Hello, World!
print(f()) # 输出: Hello, World!6.2 带参数的 lambda 函数
add lambda x, y: x y
print(add(5, 3)) # 输出: 86.3 带有默认参数的 lambda 函数
power lambda x, n2: x ** n
print(power(2)) # 输出: 4 (2^2)
print(power(2, 3)) # 输出: 8 (2^3)6.4 使用条件表达式的 lambda 函数
max_value lambda a, b: a if a b else b
print(max_value(10, 20)) # 输出: 20使用场景 lambda 函数最常用于需要将一个小函数作为参数传递给其他函数的场合比如高阶函数如 map(), filter(), sorted() 等。
1. map() 函数 map() 函数可以对可迭代对象中的每个元素应用一个函数并返回一个新的迭代器。
numbers [1, 2, 3, 4]
squared_numbers map(lambda x: x ** 2, numbers)
print(list(squared_numbers)) # 输出: [1, 4, 9, 16]2. filter() 函数 filter() 函数可以根据指定条件过滤可迭代对象中的元素。
numbers [1, 2, 3, 4, 5, 6]
even_numbers filter(lambda x: x % 2 0, numbers)
print(list(even_numbers)) # 输出: [2, 4, 6]3. sorted() 函数
sorted() 函数可以根据指定的关键字对可迭代对象进行排序。
students [{name: Alice, age: 25},{name: Bob, age: 20},{name: Charlie, age: 22}
]sorted_students sorted(students, keylambda student: student[age])
print(sorted_students)
# 输出: [{name: Bob, age: 20}, {name: Charlie, age: 22}, {name: Alice, age: 25}]4. 在列表推导式中使用 lambda 虽然列表推导式本身已经很简洁了但在某些情况下结合 lambda 函数可以进一步简化代码。
numbers [1, 2, 3, 4]
doubled [(lambda x: x * 2)(n) for n in numbers]
print(doubled) # 输出: [2, 4, 6, 8]7. Python垃圾回收机制
Python 的垃圾回收机制Garbage Collection, GC主要用于自动管理内存释放不再使用的对象所占用的内存资源。理解 Python 的垃圾回收机制有助于编写更高效的代码并避免内存泄漏等问题。
7.1 引用计数Reference Counting
这是 Python 最基本的垃圾回收机制。每个对象都有一个引用计数器记录当前有多少个引用指向该对象。当引用计数变为零时说明没有其他对象在使用它可以安全地释放其占用的内存。
工作原理
当一个对象被创建并赋值给一个变量时该对象的引用计数加一。当有新的变量引用同一个对象时引用计数再次加一。当某个变量不再引用该对象时引用计数减一。当引用计数降为零时Python 自动调用该对象的 __del__ 方法如果定义了然后释放其占用的内存。
7.2 循环引用检测Cycle Detection
虽然引用计数机制简单高效但它无法处理循环引用的情况。例如两个对象相互引用形成一个闭环即使这些对象已经没有任何外部引用它们的引用计数也不会降为零从而导致内存泄漏。
为了解决这个问题Python 使用了一个基于 标记-清除Mark-and-Sweep 和 分代收集Generational Garbage Collection 的算法来检测和清理循环引用。
工作原理
标记-清除算法分为两个主要阶段标记阶段 和 清除阶段。
标记阶段
从根对象如全局变量、活动栈帧等开始遍历所有可达对象并将这些对象标记为活跃对象。根对象是指那些始终可以被访问的对象例如当前正在使用的变量、函数调用栈中的局部变量等。
清除阶段
扫描整个堆内存找到未被标记的对象并将其删除。清除阶段会释放这些对象占用的内存并将其返回给可用内存池。
假设我们有以下对象图
A - B
B - C
C - D
D - E
E - A (循环引用)在这个例子中A - B - C - D - E - A 形成了一个循环引用。如果没有其他外部引用指向这些对象那么即使引用计数不会降为零这些对象也应该被回收。
标记阶段
从根对象开始遍历假设只有 A 被根对象引用。遍历 A发现它引用了 B标记 B。遍历 B发现它引用了 C标记 C。 继续遍历C 和 D标记 D 和 E。最终所有对象都被标记为活跃对象。
清除阶段
扫描整个堆内存发现没有未被标记的对象因此不需要清除任何对象。
如果根对象不再引用 A则在标记阶段无法到达 A 及其循环引用链上的对象这些对象会被标记为不可达并在清除阶段被删除。
分代回收Generational Garbage Collection
分代回收是一种优化策略基于一个观察大多数对象在创建后很快就会被销毁而那些存活较长时间的对象不太可能被销毁。因此Python 将对象分为三个世代Generation分别是第 0 代、第 1 代和第 2 代。
工作原理 (1) 对象分配与提升 新创建的对象属于第 0 代。当第 0 代对象经过一次垃圾回收后仍然存活它会被提升到第 1 代。类似地第 1 代对象经过垃圾回收后仍然存活则会被提升到第 2 代。 (2) 垃圾回收频率 第 0 代对象的垃圾回收频率最高因为它们最有可能被快速销毁。第 1 代和第 2 代对象的垃圾回收频率逐渐降低因为它们更有可能长期存活。 (3) 阈值设置 每个世代都有一个阈值表示在该世代对象数量达到一定值时触发垃圾回收。默认的阈值可以通过 gc.get_threshold() 获取并且可以通过 gc.set_threshold(gen0, gen1, gen2) 进行设置。
8 多线程与多进程
在 Python 中多线程Multithreading和多进程Multiprocessing是两种常见的并行编程方法用于提高程序的性能和响应速度。尽管它们都旨在实现并发执行但它们的工作原理和适用场景有所不同。
CPU密集型任务 CPU 密集型任务是指那些主要依赖于 CPU 计算能力的任务。这类任务通常需要大量的计算资源包括复杂的数学运算、数据处理、图像处理、视频编码等。 I/O 密集型任务 I/O 密集型任务是指那些主要依赖于外部输入输出操作的任务。这类任务通常涉及大量的文件读写、网络请求、数据库查询等。
8.1 多进程
基本概念
多进程是指在一个程序中同时运行多个进程。每个进程都有独立的内存空间和解释器实例 因此它们可以真正并行执行任务不受 GIL 的限制。
工作原理
8.1.1进程间通信IPC
进程之间不能直接共享内存必须通过特定的机制进行通信如Queue、Pipe 或 Manager 对象。multiprocessing.Queue 提供了一个线程和进程安全的队列用于在不同进程之间传递数据。multiprocessing.Pipe 提供了双向通信通道适用于父子进程之间的通信。
8.1.2 创建和管理进程
使用 multiprocessing.Process 类来创建和管理进程。进程可以通过调用 start() 方法开始执行并通过 join() 方法等待进程完成。
示例代码
python
深色版本
import multiprocessing
import timedef print_numbers(queue):for i in range(5):queue.put(f数字: {i})time.sleep(1)def print_letters(queue):for letter in ABCDE:queue.put(f字母: {letter})time.sleep(1)if __name__ __main__:# 创建一个队列用于进程间通信queue multiprocessing.Queue()# 创建进程p1 multiprocessing.Process(targetprint_numbers, args(queue,))p2 multiprocessing.Process(targetprint_letters, args(queue,))# 启动进程p1.start()p2.start()# 从队列中读取数据并打印while True:if not queue.empty():print(queue.get())if not p1.is_alive() and not p2.is_alive():break# 等待两个进程完成p1.join()p2.join()8.2 多线程Multithreading
基本概念
多线程是指在一个进程中同时运行多个线程。每个线程都是一个独立的执行路径可以并发执行不同的任务。Python 的 threading 模块提供了对多线程的支持。
工作原理
1GILGlobal Interpreter Lock
CPython 解释器使用 GIL 来确保同一时刻只有一个线程在执行 Python 字节码Python 源代码被编译成字节码这是一种低级的中间表示形式由 Python 虚拟机解释执行。这意味着即使有多个线程它们也不能真正并行执行CPU 密集型任务。但是对于 I/O 密集型任务如文件读写、网络请求等多线程仍然可以提高效率因为这些任务在等待 I/O操作时会释放 GIL允许其他线程继续执行。
2创建和管理线程
使用 threading.Thread 类来创建和管理线程。线程可以通过调用 start() 方法开始执行并通过 join() 方法等待线程完成。
知识扩展
GIL 的作用
简化内存管理 GIL 简化了 Python 内存管理的设计使得解释器不需要处理复杂的线程同步问题。保护内置数据结构 许多 Python 内置的数据结构和库并不是线程安全的GIL 提供了一种简单的保护机制防止多个线程同时修改这些数据结构。
为什么说 Python 的多线程是“假的”
无法实现真正的并行计算由于 GIL 的存在多线程不能真正并行执行 CPU 密集型任务。即使在多核 CPU 上也只能有一个线程在执行Python 字节码这与我们通常理解的多线程并行计算相悖。增加了上下文切换的开销在某些情况下特别是当线程频繁切换时上下文切换的开销可能会导致性能下降甚至比单线程执行还要慢。误导性初学者可能会误以为使用多线程可以显著提升程序的性能尤其是在 CPU 密集型任务中但实际上效果并不明显甚至可能适得其反。
示例代码
import threading
import timedef print_numbers():for i in range(5):print(f数字: {i})time.sleep(1)def print_letters():for letter in ABCDE:print(f字母: {letter})time.sleep(1)# 创建线程
t1 threading.Thread(targetprint_numbers)
t2 threading.Thread(targetprint_letters)# 启动线程
t1.start()
t2.start()# 等待两个线程完成
t1.join()
t2.join()