曲曲的秘密学术基地

纯化欲望、坚持严肃性

欢迎!我是曲泽慧(@zququ),目前在深圳(ICBI,BCBDI,SIAT)任职助理研究员。


病毒学、免疫学及结构生物学背景,可以在 RG 上找到我已发表的论文

本站自2019年7月已访问web counter

python 魔法方法 (3) 反运算 一元操作符

整理自小甲鱼鱼C论坛

反运算

执行反运算时首先观察加法规则:

$$ a + b $$

这个加法中,首先来确定谁是加法的主动一方,谁是被加一方。a 是主动实施加法的一方,而b则是被加一方。而反运算描述的就是被加一方的相关的算数性质。

如下:

calss Nint(int):
    def __rsub__(self, other)
        return int.__sub__(other, self)

>>> a = Nint(5)
>>> b = Nint(3)
>>> a + b    #当存在主动加法施加的a时,将会调用a的__add__()
8
>>> 1 + b    #当第一个数是常数,不具备__add__()时,就只会调用b的被加一方的__radd__()方法
-2

这里要注意otherself的顺序,如下,

class Nint(int):
    def __rsub__(self, other):
        return int.__sub__(self, other)

>>> a = Nint(5)
>>> 3 - a
2

除了例子中的__rsub__()方法外,还有以下的反运算相关的魔法方法,

魔法方法 含义
radd(self, other) 定义加法行为:
rsub(self, other) 定义减法行为:-
rmul(self, other) 定义乘法行为:*
rtruediv(self, other) 定义真除法行为:/
rfllordiv(self, other) 定义整数除法://
rmod(self, other) 定义取模算法:%
rpow(self, other) 定义当被power()调用算法:**
以下为汇编行为  
rlshift(self, other) 定义按位左移位行为:«
rrshift(self, other) 定义按位右移位行为:»
rand(self, other) 定义按位与操作行为:&
rxor(self, other) 定义按位异或操作行为:^
ror(self, other) 定义按位或操作行为:

需要注意的是,以上操作都在相应操作数不支持相应操作时被调用

一元操作符

Python 支持的一元操作符:

一元操作符 含义
neg() 表示负号行为
pos() 表示正号行为
abs() 表示取绝对值时被调用的行为
invert() 表示定义按位取反的行为

问题:

(1) 如何在继承的类中调用基类的方法?

class Derived(Base):
    def meth(self):
        super(Derived, self).meth()

(2) 如果继承的基类是动态的,如何部署代码?

可以先为基类定义一个别名,在类定义时,使用别名代替你要继承的基类。如此,当想要改变基类的时候,只需要修改给别名赋值的那个语句即可。当资源是视情况而定的时候,这个方法很好用。代码示例如下,

BaseAlias = BaseClass

class Derived(BaseAlias):
    def meth(self):
        BaseAlias.meth(self)
        ...

(3) 举例说明静态,并指出使用类的静态方法的优点

class C:
    @staticmethod # 该修饰符表示static()是静态方法
    def static(arg1, arg2, arg3):
        print(arg1, arg2, arg3):
    
    def nostatic(self):
        print('nostatic

静态方法最大的优点,就是不会绑定到实例对象上,节省开销

>>> c1 = C()
>>> c2 = C()
# 静态方法只在内存中生成一个,节省开销
>>> c1.static is C.static
True
>>> c1.nostatic is C.nostatic
False
>>> c1.static
<function C.static at 0x03001420>
>>> c2.static
<function C.static at 0x03001420>    #注意这里c1和c2实例对象的静态方法地址相同
# 以下是动态方法,注意与静态方法的比较,开销很大
>>> c1.nostatic
<bound method C.nostatic of <__main__.C object at 0x03010590>>
>>> c2.nostatic
<bound method C.nostatic of <__main__.C object at 0x032809D0>>
>>> C.nostatic
<function C.nostatic at 0x038D2B8>

需要注意,静态方法不需要self参数,因此即使是使用对象去访问,self参数也无法传输进去

(4) 定义一个类,当实例化该类时,自动判断传入了多少参数,并显示出来。效果如下,

>>> c = C()
并没有传入参数
>>> c = C(1, 2, 3)
传入3个参数分别是: 1, 2, 3

代码如下:

class ShowNum:
    def __init__(self, *args):
        if not args:
            print('并没有输入参数')
        else:
            print('传入%d个参数'% len(args), end='')
            for each in args:
                print(each, end=' ')
Last One

汇编语言 9.4 9.5 9.6 转移的目的地址以及转移地址在寄存器和内存中的jmp指令

9.4 转移的目的地址在指令中的jmp指令之前的jmp指令语法都是相当于当前IP的转移位移。jmp far ptr 标号 该命令实现的是段间转移,这种转移也被成为远转移。功能如下:(CS)=标号所在段的段地址;(IP)=标号在段中的偏移地址。如下指令,assume cs:codesg codesg segment start:mov ax, 0 mov bx, 0 jmp far ptr s db 256 dup (0) ...…

汇编语言More
Next One

汇编语言 9.1 9.2 9.3 offset jmp 依据位移进行转移的jmp指令

9.1 操作符offsetoffset在汇编语言中是由编译器处理的符号,它的功能是取得标号的偏移地址。如下代码,assume cs:codesgcodesg segment start: mov ax, offset start ;equal to: mov ax, 0 s: mov ax, offset s ;equal to: mov ax, 3codesg endsend start这里offset start相当于指明并取得start处的偏移地址0,offs...…

汇编语言More