SI100B学习笔记
SI100B,即我校的信息科学与技术“导论”,在本学期成为了一门超级加速课程。
Python
鉴于我校第一学期程设内容使用\(\rm Python\),我觉得还是要来归纳一下。
另外吐槽一下我校的循环课件,为啥可以在概念B没讲之前就可以说概念A是概念B,太离谱了。
以下内容中,\(\rm invoke\)统一翻译为“激活”,\(\rm call\)统一翻译为“调用”。
parameter n. 形式参数
argument n. 实际参数
Python's feature
\(\rm Python\)中的很多类型声明都只是给程序员看的,用于提高可读性。实际类型将由定义决定。动态类型属实坏文明
全局变量声明将会被“优先”读到,只要进入了一个作用域(\(\rm enclosing\ scope\)),就会直接看是否有\(\rm global\)声明变量。
list.append()
在存放class时,似乎其实是把类或者类的实例对象的地址放进去,所以更新类或者类的实例对象本身也会改变list内对应位置的值。
例外
\(\rm Python\)中有非常丰富的例外结构,与此同时你也可以自定义例外。
奇怪的函数积累
sorted
是一个排序方法(指\(\rm method\)),但你为啥要用完成时\(\cdots\cdots\)
.index()
是list
的通过值来索引第一个下标的函数。
.format()
可以将字符串中的{}
替换成format内给定的字符串。多个{}
会按顺序替换。
OOP
对于面向对象我还并没有完全理解,不过靠搜索引擎大概学会了一点:
总体上来说,面向对象编程就是并非从宏观上统一解决问题,而是将问题划分为不同对象的行为组合。
此外,以下内容都在\(\rm Python\)语境中,可能与其他语言有些许出入。
Instance Object/实例对象
简单来说就是创建一个可以独立出来用的玩意儿。如果实例对象对应的类增减了某种属性,该对象也会对应增减某种属性。
可以使用isinstance(obj,cls)
来判断前者是否是后者的实例对象。另外,类(类对象)也是类型的实例对象。
Instance Variable/实例变量
变量是对象的属性。在后文中,可能会为了语义的通顺将“变量”和“属性”混用。
实例变量是每一个实例的独立数据,比如
obj.var
的var
就是obj
这个实例对象的实例变量。
实例变量可以被动态添加至对象中,但是这个变量是只存在于这个对象中的独立变量。
实例变量也可以被删除(析构),删除后其所属的对象将不再具有该属性。
\(\rm slides\)上推荐将所有的实例变量都在构造函数中初始化。
实例变量可以是函数。
Class Variable/类变量
与实例变量类似,它是类的独立数据,所以它可以被类的所有实例对象共享。
它的特性与实例变量很相似,不再赘述。
\(\rm slides\)上推荐将所有的类变量都在类的定义开头初始化。
Instance Method/实例方法
需要注意的是,根据变量的定义,方法也是变量。
这\(\rm method\)的译名大概和机翻没有区别。
实例方法是操作实例数据的函数,所有实例方法的第一个形参都会绑定实例对象,且标识符无限制,但通常使用self
。
需要注意的是,实例方法无法直接用赋值的形式动态添加,这样只会得到一个实例变量,当然这个变量是函数,但它不是方法,因此你需要在调用函数的时候写入第一个参数来调用目标对象。
想要对某个对象动态添加一个实例方法,可以
import types
然后使用types.MethodType(func,obj)
来将func
函数添加为obj
对象的实例方法。此时第一个形参将自动调用当前实例对象。
实例方法也可以被删除,删除后其所属的对象将不再具有该属性。
\(\rm slides\)上推荐将所有的实例方法都在类的定义中定义。
Class Method/类方法
与实例方法类似,类方法是操作类数据的函数,所有实例方法的第一个形参都会绑定类对象,且标识符无限制,但通常使用cls
。
定义类方法时,一般可以添加一个名为“装饰器”的语法糖来宣称这个函数是类方法。
动态添加与删除的方式与实例方法类似。
Access/访问
实例变量可以直接访问。
实例方法可以直接obj.f(...)
访问,也可以通过
cls.f(obj,...)
来访问cls
类的obj
实例方法。
类变量可以直接访问,也可以通过实例对象访问。
类方法可以直接访问,也可以通过类对象访问,且二者都不需要写入第一个形参。
需要注意的是以上方法必须要满足所有的变量都不相同。
Private & Public Attributes/属性的属性(?)
\(\rm Python\)中运用下划线来定义特殊属性,但这带来了一些奇怪的问题。
_x
表示该变量的属性是protected
,但在\(\rm Python\)中,它仅能保护其不被
from module import
输入。
__x__
表示该变量由系统定义。
__x
表示该变量的属性是private
,即它只能被该类内的实例方法访问且不能被继承这个概念我以前接触过所有就在没写之前用了。如果需要在类外访问,可以用
obj._cls__x
Special Method Names/特殊方法名称
接下来会介绍一些特殊的方法,它们拥有特殊的高亮。
这些方法是\(\rm Python\)运算符重载的方式,它们可以在让类定义它们自己的行为的同时“尊重”语法本身的运算符。
它们本身能够自定义,但不应当被显式调用,而是被编译器调用。
\(\rm Constructor/\)构造函数
即__init__(self,...)
,是所有的类都有的一个隐式实例方法。
它会在创建类的新实例对象的时候自动被调用。
\(\rm Destructor/\)析构函数
即__del__(self)
。
\(slides\)中写到当对象的引用计数为\(0\)时对象被将销毁,对象将被销毁的时候会调用这个函数。但很显然我并不知道“引用计数”是什么。
\(\rm Creator/\)翻译没找到
即__new__(cls,...)
。
它会将请求实例对象的类放在第一个参数,其它参数会传给__init__(self,...)
。
它会在构造函数激活前返回新的实例对象,目前不清楚它的具体应用。
\(\rm Iterator/\)迭代器
即__iter__(self)
。它可自定义迭代器的初始值。
\(\rm Generator/\)翻译没找到
即__next__(self)
。它可自定义迭代器的变化量。
如果在类中自定义了\(\rm Generator\),迭代器直接返回self
即可。
为了防止双重循环迭代出现问题,建议将该方法写在另一个类中,迭代器直接返回anothercls(self)
即可。
\(\rm Operators/\)运算符
加减乘除整除取模幂偏序位移逻辑,还有一个对象的字符串表示。
Inheritance/继承
继承是除了函数、类、模块外另一种重复运用代码的方式。它的使用方法是
class subcls(basecls)
子类(派生类)与基类(父类)别问我为什么要缝合两种译法的关系比较类似于\(\rm fork\),但它\(\rm fork\)的时候并不能完整的复制基类的所有内容。
所有属性为public
和protected
的实例方法都能被继承,但当且仅当子类没有覆写基类的构造函数,或子类的构造函数显式激活了基类的构造函数时,所有的实例变量才能被继承。
需要注意的是,新的和覆写后的方法无法访问基类的private
变量,但继承下来的可以。
Signal Processing
傅里叶变换/Fourier Transform
真巧,OI笔记也写到了傅里叶变换。其实是因为拖了好久还没写完
信号处理中的傅里叶变换主要是指信号在时域与频域之间的变换。
我们假设一个信号在时域的函数为\(g(t)\),那么它在频域的函数\(\hat{g}(f)=\int_{-\infty}^{+\infty}e^{-2\pi ift}dt\)。
这个式子初看是相当难以理解的,可以参考3B1B的视频。
卷积/Convolution
此处的卷积其实是用一个Convolution Kernel(卷积核)逐位置对图像进行对应位置乘法操作,并将值赋予中心点。
其中Gaussian Blur Kernel(高斯模糊核)即二维正态分布,可以自定义半径和方差。
直方图均衡化/Histogram Equalization
大概就是让一个图的亮度均衡化,先将RGB转换成YUV,再统计本质不同的亮度个数,用公式转换每一个像素的亮度,随后再转换为RGB输出。
音频的形成/the Born of Audio
音频信号的形成需要经过两步:采样和量化。
所谓采样率,即每秒对音频的采样次数,经典的如44100Hz。
采样之后,由于音频的响度也是连续的,因此也需要近似表示,即量化。
Electronic Engineering
别问,问就是咕了。