python
函数
函数和模块的使用
$$
一道数学题:x1+x2+x3+x4 = 8 有多少组正整数解?
$$
等同于 将八个苹果 分成四组,每组至少一个苹果
$$C_M^N =\frac{M!}{N!(M-N)!}, \text{(M=7, N=3)} $$
python 的实现:
def fac(num): |
使用函数减少重复。
函数的参数
可以有默认值,也可以是可变参数
设置默认值:
def add(a =0,b = 0,c = 0):
return a+b+c
print(add()) #使用默认值
print(add(1))
print(add(1, 2))
print(add(1, 2, 3)) #以上三种是按顺序传递参数
print(add(c=50, a=100, b=200)) #不按照顺序传递不清楚参数个数,使用可变参数:
在参数之前 * 表示是一个可变参数
def add(*a): |
用模块管理函数
在python 中没有函数重载,所以后面的相同命名函数 会替代前者。
所以为了避免,使用模块,python 中每个文件都代表了一个模块(module)
- module1.py
def foo():
print('hello, world!') - module2.py
def foo():
print('goodbye, world!') - test3.py 或者
from module1 import foo
# 输出hello, world!
foo()
from module2 import foo
# 输出goodbye, world!
foo()
这里的两个as必须是不同的东西,不然前者会被后者替代。
import module1 as m1
import module2 as m2
m1.foo()
m2.foo()
注意:当我们编写的module 中除了要引用的函数,还包含其他可执行的代码时 最好将执行代码放入如下所示条件中
- module3.py
def foo():
...
def bar():
...
# __name__是Python中一个隐含的变量它代表了模块的名字
# 只有被Python解释器直接执行的模块的名字才是__main__
if __name__ == '__main__':
print('call foo()')
foo()
print('call bar()')
bar()
函数的嵌套
目的:创建闭包
。生成一个会根据外部作用域参数动态变化的函数。就是内部函数可以访问外部函数变量。
简单理解就是:闭包可以保存状态,保存外部函数的状态
什么时候会用到闭包呢?
- 想要一个带有特定行为的函数
def 外部函数(参数): |
每当我们调用内部函数中的时候,外部的参数仍然是可以访问的。
变量的作用域
Python查找一个变量时会按照“局部作用域”、“嵌套作用域”、“全局作用域”和“内置作用域”的顺序进行搜索
权重大小相反
如果我们想要在内部函数中修改全局作用域的变量,需要使用 global
如果望函数内部的函数能够修改嵌套作用域中的变量,需要使用 nonlocal
def foo(): |
正则表达式
形式
lambda <参数/变量> : 表达式
把参数返回到后面的表达式中,不需要使用return
#与函数的比较 |
当牵涉到把一个函数作为变量传入另一个函数中,一般把要作为变量的函数以正则表达式的形式给出
def cube(k):
return k*k
summation(5,cube)
summation (5,lambda k:k*k)
条件表达
面向对象编程
类/对象
- class 关键字创建类,引用创建对象。
class myclass:
x = 5
p1 = myclass() #创建对象
print(p1.x)这里 p1 叫做对象的实例,只是一个变量名。
如何在python 中创建实例(对象)
通过键入类的名称,然后键入左括号和右括号来创建新对象:
class Dog: |
两次创建的实例位于不同的内存地址,两者不相同
- 函数
self 属于该类的当前实例的引用“当前对象的感觉”
class Person: |
self
用于访问属于该类的变量。可以随便命名,必须是类中任何函数的第一个参数。修改对象属性
p1.age = 40 #修改年龄为40岁
删除对象属性
del p1.age
删除对象
del p1init()函数
所有函数都有这个函数,当类被初始化的时候使用。每次创建新对象的时候也会自动调用该函数。
这个函数为对象属性分配值,或其他操作。str()函数
控制类的对象是字符串的时候应该返回的内容。
|
- repr()函数
repr 方法应返回一个“官方”的字符串表示形式,该表示形式能够准确且唯一地描述该对象
class Fraction: |
为什么要自定义 __repr__?
默认的 repr 方法仅返回对象的内存地址
str 与 repr 的区别
前者是用户友好表示 ,当使用print() 或者 str()函数的时候,会调用__str__方法
后者是官方表示,主要面向开发者,提供详细、精确的对象信息
操作符重载
操作符:加减乘除,比较操作符(用于比较两个值的大小或相等性,返回布尔值(True 或 False)),逻辑……
允许同一操作符根据上下文具有不同的含义称为操作符重载
python 标准操作符
![屏幕截图 2024-09-24 201019](C:\Users\86151\Pictures\Screenshots\屏幕截图 2024-09-24 201019.png)
为甚么要进行重新定义一些标准操作符?
比如说,我们要比较 两个对象的实例是否相等,但是因为储存的位置不一样,所以不相等。
f1 = Fraction(2,5) |
所以需重新定义__eq__()
私人变量
self._name = name 在变量前加上下划线来标识私有变量
好处:确保数据的完整性。并且封装(隐藏内部表示,外部接口一致)
私有变量不能被对象外部的代码直接访问。要用get 或set 才能访问私有变量。
class person: |
继承
继承允许我们定义一个类,该类继承了另一个类的所有方法和属性。
父类是被继承的类,也称为基类。
class Fatherclass(): |
子类是从另一个类继承的类,也称为派生类
父类按照正常类创建,子类创建时把父类作为参数传入。
class SonClass(FatherClass): |
- init__函数
如果想在子类添加__init__函数,一般来说,子项的__init 函数会覆盖父类的__init__函数。为了保证继承,我们添加对父类函数的调用。
class SonClass(FatherClass): |
- super()函数
在python 中也可以使用super()函数让子类继承
class Student(Person): |
递归
一个直接或者间接调用自己的函数。