Python灰帽编程——错误异常处理和面向对象

1. 错误和异常

如果遇到了错误(异常),如何去处理?

1.1 基本概念

1.1.1 Python 异常

当程序运行时,因为遇到未知的错误而导致中止运行,便会出现Traceback 消息,打印异常。异常即是一个事件,该事件会在程序执行过程中发生,影响程序的正常执行。一般情况下,在Python 无法正常处理程序时就会发生一个异常。异常是Python 对象,表示一个错误。当Python 脚本发生异常时我们需要响应处理它,否则程序会终止执行可以捕获异常。

异常描述
SyntaxError语法错误
NameError未声明/初始化对象
IndexError序列中没有此索引
KeyboardInterrupt用户中断执行(Ctrl+C)
EOFError没有内建输入,到达EOF 标记(Ctrl+D) 不适用windows 系统
IOError输入/输出操作失败
ValueError当操作或函数接收到具有正确类型但值不适合的参数, 并且情况不能用更精确的异常,例如 IndexError来描述时将被引发。
TypeError字符串与整数相加时触发。

1.2 检测(捕获)异常

如果一个语句发生了错误或异常,跳过该语句的执行,执行另外的语句。

1.2.1 try except 语句

监控异常

尝试执行try 语句,如果遇到异常(行不通)则执行except 语句。两个语句执行一个。

语法规则

try:
    pass                # 监控这里的异常
except Exception[, reason]:
    pass                # 异常处理代码

示例:

# 01 - 异常初探.py

try:		#尝试执行语句
    username = input("Please input your name: ")
    print(f"Welcome, {username}")

except:		#如果遇到异常执行的语句
    print("\nSomething Error!")

1.2.2 捕获多种异常

算命脚本:输入年龄,预测明年的年龄。

可以把多个except 语句连接在一起,处理一个try 块中可能发生的多种异常。

# 02 - 捕获多种异常.py

banner = '''
杰哥的算命脚本
1. 预测年龄
2. 预测财运
3. 预测姻缘
'''

print(banner)

choice = input("Please input the number: ")
choice = int(choice)

def guess_age():
    try:
        age = input("Please input your age: ")
        print(f"The next year your name: {int(age) + 1}")

    except ValueError:
        print("\nPlease input a number!")

    except KeyboardInterrupt:
        print("\nCtrl + C.END")

    except:
        print("\nSomething Error!")
if choice != 1:
    print("好好学习...")
    exit()
eles:
    guess_age()

1.2.3 捕获所有异常

如果出现的异常没有出现在指定要捕获的异常列表中,程序仍然会中断。可以使用在异常继承的树结构中,BaseException 是在最顶层的,所以使用它可以捕获任意类型的异常。

except BaseException:           # 捕获所有异常,相当于except
    print("\nSomething Error!")

Pyhton 异常树

BaseException                                               所有异常的基类
     |
     |
     +-- SystemExit                                         解释器请求退出
     |
     |
     +-- KeyboardInterrupt                                  用户中断执行(通常是输入^C)
     |
     |
     +-- GeneratorExit                                      生成器调用close();方法时触发的
     |
     |
     +-- Exception                          常规错误的基类,异常都是从基类Exception继承的。
          |
          +-- StopIteration                                 迭代器没有更多的值
          |
          +-- StandardError                                 所有的内建标准异常的基类
          |    +-- BufferError                              缓冲区操作不能执行
          |    +-- ArithmeticError                          所有数值计算错误的基类
          |    |    +-- FloatingPointError                  浮点计算错误
          |    |    +-- OverflowError                       数值运算超出最大限制
          |    |    +-- ZeroDivisionError                   除(或取模)零 (所有数据类型)
          |    +-- AssertionError                           断言语句失败
          |    +-- AttributeError                           访问未知对象属性
          |    +-- EnvironmentError                         操作系统错误的基类
          |    |    +-- IOError                             输入输出错误
          |    |    +-- OSError                             操作系统错误
          |    |         +-- WindowsError (Windows)         系统调用失败
          |    |         +-- VMSError (VMS)                 系统调用失败
          |    +-- EOFError                                 没有内建输入,到达EOF 标记
          |    +-- ImportError                              导入模块/对象失败
          |    +-- LookupError              无效数据查询的基类,键、值不存在引发的异常
          |    |    +-- IndexError                          索引超出范围
          |    |    +-- KeyError                            字典关键字不存在
          |    +-- MemoryError              内存溢出错误(对于Python 解释器不是致命的)
          |    +-- NameError                未声明/初始化对象 (没有属性)
          |    |    +-- UnboundLocalError                   访问未初始化的本地变量
          |    +-- ReferenceError           弱引用(Weak reference)试图访问已经垃圾回收了的对象
          |    +-- RuntimeError                             一般的运行时错误
          |    |    +-- NotImplementedError                 尚未实现的方法
          |    +-- SyntaxError                              语法错误
          |    |    +-- IndentationError                    缩进错误
          |    |         +-- TabError                       Tab 和空格混用
          |    +-- SystemError                              一般的解释器系统错误
          |    +-- TypeError                                对类型无效的操作
          |    +-- ValueError                               传入无效的参数
          |         +-- UnicodeError                        Unicode 相关的错误
          |              +-- UnicodeDecodeError             Unicode 解码时的错误
          |              +-- UnicodeEncodeError             Unicode 编码时错误
          |              +-- UnicodeTranslateError          Unicode 转换时错误
          |
          +-- Warning                                       警告的基类
               +-- DeprecationWarning                       关于被弃用的特征的警告
               +-- PendingDeprecationWarning                关于特性将会被废弃的警告
               +-- RuntimeWarning              可疑的运行时行为(runtime behavior)的警告
               +-- SyntaxWarning                            可疑的语法的警告
               +-- UserWarning                              用户代码生成的警告
               +-- FutureWarning                            关于构造将来语义会有改变的警告
               +-- ImportWarning               关于模块进口可能出现错误的警告的基类。
               +-- UnicodeWarning                           有关Unicode警告的基类。
               +-- BytesWarning                             有关字节警告相关的基类。

1.3 处理异常

try:                                                # 尝试执行某个语句
    num = int(input("The number:"))
except BaseException:                               # 如果遇到异常,执行的语句
    print("something error!")
else:                                               # 如果没有遇到异常,执行的语句
    print(num)
finally:                                            # 不管是否遇到异常,都要执行的语句。
    print("This is finally")
  • else 子句:在try 范围中没有异常被检测到时,执行else 子句。在else 范围中的任何代码运行前,try 范围中的所有代码必须完全成功。

  • finally 子句:finally 子句是无论异常是否发生,是否捕捉都会执行的一段代码。比如获取用户的输入,写入文件,但是如果在获取数据过程中,发生了异常,就会导致整个脚本结束执行,文件也无法关闭了。为了解决这个问题,可以采用异常处理中的finally 子句,也就是说,无论语句是否正常执行,都需要关闭。

# 03 - 处理异常.py

banner = '''
杰哥的算命脚本
1. 预测年龄
2. 预测财运
3. 预测姻缘
'''

print(banner)

choice = input("Please input the number: ")
choice = int(choice)

def guess_age():
    try:
        age = input("Please input your age: ")
        age = int(age) 

    except ValueError:
        print("\nPlease input a number!")

    except KeyboardInterrupt:
        print("\nCtrl + C")

    except:
        print("\nSomething Error!")

    else:
        print(f"The next year your name: {age + 1}")

    finally:
        print("杰哥算命脚本执行结束,祝你好运!")
if choice != 1:
    print("好好学习...")
    exit()
else:
    guess_age()

1.4 特殊场景

1.4.1 with 语句

with 语句是用来简化代码的。比如在将打开文件的操作放在with 语句中,代码块结束后,文件将自动关闭。用来简化文件操作的打开和关闭,其中closed 属性是判断文件是否被关闭的

>>> with open('foo.py') as f:

2. 内网主机存活检测程序

网络模型:

应用层
表示层
会话层			应用层			应用层		http|ftp|dns|dhcp
传输层			传输层			传输层		tcp|udp
网络层			网络层			网络层		ip
数据链路层	  数据链路层
物理层			物理层			网络接口层

2.1 scapy 模块

与scrapy 有非常大的区别。

scapy 是一个Python 的第三方模块,被称为“网络神器”。scapy 模块能够发送、捕获、分析和铸造网络数据包。

2.1.1 主要功能

image-20230918164702051

2.1.2 scapy 安装

Windows 下安装scapy

python -m pip install scapy

依赖

Kali 中自带scapy 环境。

2.1.3 进入scapy 模块

┌──(ajest zh-CN)-[~]
└─$ sudo scapy                     

                     aSPY//YASa       
             apyyyyCY//////////YCa       |
            sY//////YSpcs  scpCY//Pp     | Welcome to Scapy
 ayp ayyyyyyySCP//Pp           syY//C    | Version 2.4.5
 AYAsAYYYYYYYY///Ps              cY//S   |
         pCCCCY//p          cSSps y//Y   | https://github.com/secdev/scapy
         SPPPP///a          pP///AC//Y   |
              A//A            cyP////C   | Have fun!
              p///Ac            sC///a   |
              P////YCpc           A//A   | Craft packets before they craft
       scccccp///pSP///p          p//Y   | you.
      sY/////////y  caa           S//P   |                      -- Socrate
       cayCyayP//Ya              pY/Ya   |
        sY/PsY////YCc          aC//Yp 
         sc  sccaCY//PCypaapyCP//YSs  
                  spCPY//////YPSps    
                       ccaacs         
                                       using IPython 7.22.0
>>>

2.1.4 简单使用

构造数据包

>>> pkt = IP()/TCP()
>>> pkt.show()
###[ IP ]### 
  version   = 4
  ihl       = None
  tos       = 0x0
  len       = None
  id        = 1
  flags     = 
  frag      = 0
  ttl       = 64
  proto     = tcp
  chksum    = None
  src       = 127.0.0.1
  dst       = 127.0.0.1
  \options   \
###[ TCP ]### 
     sport     = ftp_data
     dport     = http
     seq       = 0
     ack       = 0
     dataofs   = None
     reserved  = 0
     flags     = S
     window    = 8192
     chksum    = None
     urgptr    = 0
     options   = ''

>>> pkt = IP(src = "192.168.1.11", dst = "192.168.1.1")/TCP()		#src:发送方dst:接收方
>>> pkt.show()
###[ IP ]### 
  version   = 4
  ihl       = None
  tos       = 0x0
  len       = None
  id        = 1
  flags     = 
  frag      = 0
  ttl       = 64
  proto     = tcp
  chksum    = None
  src       = 192.168.1.11
  dst       = 192.168.1.1
  \options   \
###[ TCP ]### 
     sport     = ftp_data
     dport     = http
     seq       = 0
     ack       = 0
     dataofs   = None
     reserved  = 0
     flags     = S
     window    = 8192
     chksum    = None
     urgptr    = 0
     options   = ''

>>>

发送数据包

发送数据包的函数说明
sr(pkt)发送数据包,接收所有返回包
sr1(pkt)发送数据包,接收(等待)一个返回包
send(pkt)发送数据包,不等待返回包
srp(pkt)发送2 层数据包,等待回应
sendp(pkt)发送2 层数据包,不等待返回包
>>> res = sr1(pkt)
Begin emission:
Finished sending 1 packets.
.*
Received 2 packets, got 1 answers, remaining 0 packets
>>>

在发送数据包的时候,再接收返回包,网卡一直处于监听状态,接收监听的数据包,一直等待回应。直到接收到返回包。接到返回包,主机在线,接不到返回包,主机不在线。

查看返回包

>>> res.show()
###[ IP ]### 
  version   = 4
  ihl       = 5
  tos       = 0x0
  len       = 44
  id        = 13990
  flags     = 
  frag      = 0
  ttl       = 255
  proto     = tcp
  chksum    = 0x46a4
  src       = 10.9.21.1
  dst       = 10.9.21.111
  \options   \
###[ TCP ]### 
     sport     = http
     dport     = ftp_data
     seq       = 1510518667
     ack       = 1
     dataofs   = 6
     reserved  = 0
     flags     = SA
     window    = 65535
     chksum    = 0x4f9c
     urgptr    = 0
     options   = [('MSS', 1460)]
###[ Padding ]### 
        load      = '\x00\x00'

>>>

2.2 主机存活检测程序

icmp的回应包:0

# 04 - 内网主机存活检测程序.py

from scapy.all import *
from scapy.layers.inet import *
from termcolor import colored

import logging
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)		#屏蔽信息的模块,scapy运行期间,只有ERROR才显示即其他的都不显示。

netmask = "192.168.16."     #接收端的网络位
src = "192.168.16.177"      #发送端

for i in range(1, 255):
    dst = f"{netmask}{i}"        #接收端

    pkt = IP(src = src, dst = dst)/ICMP()	#创建数据包
    res = sr1(pkt, timeout = 1, verbose = False)	#发送数据包等待回应,等待一秒,一秒后没有回应当作不在线,禁止详细输出
    if res and res.type == 0:
        print(colored(f"\n{dst} is ALIVE!","green"))
    else: 
        print(f"\r{dst} is NOT LIVE!!!",end = "")		#输出目的主机不存活,end=""使结果原地输出

3. 面向对象编程

编写POC平台:

goby,nuclei			
		yaml语言
		
pocsuite3			高仿msf
		py语言
		
yakit
		yak语言

3.1 类

类是一类事物的统称,比如学生。对象就是类的实例化。

类有属性(变量),比如学生的姓名、性别、年龄、成绩等,也就是编程里面的变量。

类有方法(函数),比如学生的上课、下课等,也就是编程里面的函数。

3.1.1 创建类

类是一种数据结构,我们可以用它来定义对象,对象把数据值和行为特性融合在一起。Python 使用class 关键字来创建类:通常类名的第一个字母大写,推荐使用驼峰式命名法,单词首字母均大写。类有属性(变量)和方法(动作,函数)组成。

class ClassName(bases):
    'class documentation string'    #'类文档字符串'
    class_suite                     # 类体

3.1.2 _init_ 方法

__init__() 是类的实例(对象)创建后第一个被调用的方法,通常被用来进行对象中属性(变量)的初始化。设置实例的属性可以在实例创建后任意时间进行,但是通常情况下优先在__init__() 方法中实现。

  • 定义类型
  • 实例化对象(创建一个对象)
  • 初始化对象(第一次给对象属性赋值)
# 05 - __init__.py

class Stu():
    #self:是一个特殊的参数,他对类的实例(对象)本身。在类的方法中,只用self参数可以访问该对象的属性和方法
    def __init__(self, name, sex, age, score):
        self.name = name
        self.sex = sex
        self.age = age
        self.score = score

stu1 = Stu(name = "XJ", sex = True, age = 24, score = 59.9)	#在传参的时候,stu1传给类中的self,name传给类中的name...在类中相当于:stu1.name = "XJ",stu1.sex = True,stu1.age = 24...

print(f"{stu1.name} 的成绩是{stu1.score}")

3.2 方法

3.2.1 绑定方法

方法仅仅是类内部定义的函数,方法只有在其所属的类拥有实例时,才能被调用;任何一个方法定义中的第一个参数都是变量self,它表示调用此方法的实例对象就是自己。

类中的方法,也就是类中定义的函数,这个函数第一个参数永远是self,表示自己。

# 06 - 绑定方法.py

import time

class Stu():
    def __init__(self, name, sex, age, score):
        self.name = name
        self.sex = sex
        self.age = age
        self.score = score

    def getSocre(self):
        print(f"{self.name} 的成绩是{self.score}")

    def goodGoodStudy(self):
        print("好好学习中...")
        time.sleep(10)
        self.score += 0.1


stu1 = Stu(name = "LH", sex = True, age = 24, score = 59.9)
stu2 = Stu(name = "HMM", sex = True, age = 24, score = 89.9)

stu2.getSocre()
stu2.goodGoodStudy()
stu2.getSocre()

3.3 继承

3.3.1 子类继承

继承描述了基类(祖先)的属性如何遗传给派生类(子孙),子类可以继承它的基类的任何属性,不管是数据属性还是方法。

# 34 - 子类继承.py

import time

class Kid():
    def __init__(self, name = "", sex = "", age = ""):
        self.name = name
        self.age = age
        self.sex = sex

    def play(self):
        print("玩游戏中...")

class Stu(Kid):
    def __init__(self,name = "", sex = "", age = "", score = ""):
        Kid.__init__(self, name, sex, age)
        self.score = score

    def get_score(self):
        print(f"{self.name} 的成绩是{self.score}")

    def good_good_study(self):
        print("好好学习中...")
        time.sleep(10)
        self.score += 0.1

stu1 = Stu(name = "XJ", sex = True, age = 24, score = 59.9)
stu2 = Stu(name = "LL", sex = True, age = 25, score = 49.9)
stu3 = Stu(name = "HMM", sex = True, age = 23, score = 99.9)
stu4 = Stu(name = "LH", sex = True, age = 24, score = 79.9)

stu1.play()

3.3.2 方法重写

如果子类中有和父类同名的方法,父类方法将被覆盖;如果需要访问父类的方法,则要调用一个未绑定的父类方法,明确给出子类的实例。

# 08 - 方法重写.py

import time

class Kid():
    def __init__(self, name, sex, age):
        self.name = name
        self.sex = sex
        self.age = age

    def play(self):
        print("玩游戏中...")

class Stu(Kid):
    def __init__(self, name, sex, age, score):
        Kid.__init__(self, name, sex, age)
        self.score = score	#Stu类继承了Kid类。在它的构造函数中,除了接受与Kid相同的三个参数外,还接受一个额外的参数score(分数)。Kid.__init__(self, name, sex, age)用于调用父类Kid的构造函数,以便初始化父类的属性。同时,Stu类还定义了一个自己的属性score,并将score的参数值赋给它。

    def getSocre(self):
        print(f"{self.name} 的成绩是{self.score}")

    def goodGoodStudy(self):
        print("好好学习中...")
        time.sleep(10)
        self.score += 0.1

    def play(self):
        print("玩王者荣耀中...")
        time.sleep(2)
        self.score -= 10

stu1 = Stu(name = "AJEST", sex = True, age = 24, score = 59.9)
stu2 = Stu(name = "HMM", sex = True, age = 24, score = 89.9)

stu2.getSocre()
stu2.play()
stu2.getSocre()
stu2.goodGoodStudy()
stu2.goodGoodStudy()
stu2.getSocre()
stu2.play()
stu2.getSocre()

3.3.3 多重继承

Python 允许多重继承,即一个类可以是多个父类的子类,子类可以拥有所有父类的属性。

# 09 - 多重继承.py

class A():
    def a(self):
        print("This is function A!")

class B():
    def b(self):
        print("This is function B!")

class C(A, B):
    pass
C = C()
C.a()
C.b()

解释:

  • 在Python中,pass 是一个空语句,不执行任何操作。当你在代码中遇到需要写一段代码但又暂时没有实现的情况时,可以使用 pass 来占位,使得代码结构完整而没有语法错误。

  • 多重继承是指一个类可以继承自多个父类的特性和方法。在Python中,多重继承可以通过在类定义时指定多个父类来实现。

    当一个类继承自多个类时,它继承了这些父类的属性和方法。这意味着子类可以使用来自所有父类的特性,并且可以在自己的定义中添加新的属性和方法。

    下面是一个简单的示例,演示了多重继承的概念:

    class A:
        def method_a(self):
            print("这是A类的方法")
    
    class B:
        def method_b(self):
            print("这是B类的方法")
    
    class C(A, B):
        def method_c(self):
            print("这是C类的方法")
    
    # 创建C类的对象
    obj = C()
    
    # 调用来自父类A和B的方法
    obj.method_a()  # 输出:这是A类的方法
    obj.method_b()  # 输出:这是B类的方法
    
    # 调用自己的方法
    obj.method_c()  # 输出:这是C类的方法
    

    在上面的代码中,类A和B分别定义了method_a和method_b两个方法。类C继承自A和B,因此它拥有这两个父类的方法。然后,通过创建C类的对象obj,我们可以调用来自父类A和B的方法,也可以调用C类自己的方法method_c。

    需要注意的是,当一个类继承自多个父类时,如果不同父类中存在同名的方法或属性,Python解释器将按照特定的顺序(称为方法解析顺序)来查找和调用。方法解析顺序由C3线性化算法确定,它确保解析顺序是一种合理且一致的方式。在Python中,可以使用c3_linearize()函数来查看类的方法解析顺序。

    多重继承的使用必须慎重,因为它可以引起一些复杂的问题,例如方法冲突和命名空间冲突。因此,在使用多重继承时,需要仔细考虑类与类之间的关系,以及方法和属性的命名以避免冲突。

3.4 魔法函数

3.4.1 类和实例的内建函数

函数作用
issubclass()判断一个类是另一个类的子类或子孙类
isinstance()判定一个对象是否是另一个给定类(可以是一个父类的子孙类,也可以是一个子类的父类)的实例
hasattr()判断一个对象是否有一个特定的属性
getattr()获得一个对象的属性值
setattr()设置一个对象的属性
delattr()删除一个对象的属性

3.4.2 常用的魔法函数

魔法函数是系统自带的,会在“恰当”的时候自动调用。

# 10 - 魔术方法.py

class Test():
    def __init__(self):
        print("Function __init__ is called!")

    def __str__(self):
        return "Why print(self)?"

    def __call__(self):
        print("Why call me like Function?")

t = Test()

print(t)

t()

解释:

在Python中,魔法函数(Magic methods)是一类特殊的函数,以双下划线(__)开头和结尾的方法。它们也被称为特殊方法或双下方法。

魔法函数在Python中用于定义自定义类的行为,使其具有类似内置类型的行为。当某些特定的操作发生时(例如实例创建、对象调用、属性访问等),魔法函数会被自动调用。

下面是一些常见的魔法函数的详细解释和示例:

  1. __init__: 这是一个构造函数,用于创建对象实例。它在对象被创建时自动调用,常用于初始化对象的属性。

    class Person:
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
    person = Person("John", 30)
    print(person.name)  # 输出: John
    print(person.age)   # 输出: 30
    
  2. __str____repr__: __str__ 用于定义对象的字符串表示形式,对于用户的友好输出有很大作用;而 __repr__ 则用于定义对象的技术细节表示形式,主要用于调试和开发。

    class Person:
        def __init__(self, name, age):
            self.name = name
            self.age = age
        
        def __str__(self):
            return f"Person(name={self.name}, age={self.age})"
        
        def __repr__(self):
            return f"Person(name='{self.name}', age={self.age})"
    
    person = Person("John", 30)
    print(str(person))   # 输出: Person(name=John, age=30)
    print(repr(person))  # 输出: Person(name='John', age=30)
    
  3. __len__: 该方法定义了对象的长度。使用内建函数 len() 调用对象时,实际上是调用了对象的 __len__ 方法。

    class MyList:
        def __init__(self, elements):
            self.elements = elements
        
        def __len__(self):
            return len(self.elements)
    
    my_list = MyList([1, 2, 3, 4, 5])
    print(len(my_list))  # 输出: 5
    
  4. __getitem____setitem__: 这些方法定义了对象的索引操作行为。可以通过方括号 [] 访问对象中的元素,而实际上是调用了对应的魔法函数。

    class MyList:
        def __init__(self, elements):
            self.elements = elements
        
        def __getitem__(self, index):
            return self.elements[index]
        
        def __setitem__(self, index, value):
            self.elements[index] = value
    
    my_list = MyList([1, 2, 3, 4, 5])
    print(my_list[2])    # 输出: 3
    my_list[2] = 10
    print(my_list[2])    # 输出: 10
    
  5. __call__: 使得对象可以像函数一样被调用。在对象后面加括号时,会自动调用该对象的 __call__ 方法。

    class Calculator:
        def __call__(self, a, b):
            return a + b
    
    calculator = Calculator()
    result = calculator(3, 5)
    print(result)  # 输出: 8
    

还有很多其他的魔法函数,例如 __add__(用于定义对象相加操作)、__sub__(用于定义对象相减操作)、__eq__(用于定义对象相等比较操作)等等。通过定义这些魔法函数,可以使得自定义类的实例表现得更加像内置类型,提供更多的灵活性和可定制性。

3.5 私有化

Python 为类元素(属性和方法)的私有性提供初步的形式,由双下划线开始的属性在运行时被“混淆”,所以直接访问是不允许的。

# 11 - 私有化.py

# 06 - 绑定方法.py

import time

class Stu():
    def __init__(self, name, sex, age, score):
        self.name = name
        self.sex = sex
        self.age = age
        self.__score = score

    def getSocre(self):
        print(f"{self.name} 的成绩是{self.__score}")	#允许访问成绩

    def goodGoodStudy(self):
        print("好好学习中...")
        time.sleep(10)
        self.__score += 0.1

stu1 = Stu(name = "AJEST", sex = True, age = 24, score = 59.9)
stu2 = Stu(name = "HMM", sex = True, age = 24, score = 89.9)

stu2.getSocre()
ator()
   result = calculator(3, 5)
   print(result)  # 输出: 8

还有很多其他的魔法函数,例如 __add__(用于定义对象相加操作)、__sub__(用于定义对象相减操作)、__eq__(用于定义对象相等比较操作)等等。通过定义这些魔法函数,可以使得自定义类的实例表现得更加像内置类型,提供更多的灵活性和可定制性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

网安咸鱼1517

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值