了解基础魔法函数学会封装和继承新建模块和函数使用异常

news2025/2/8 5:46:31

一、魔法函数

1.1、概念:

魔法函数(magic methods)是指以双下划线开头和结尾的特殊方法,用于实现对象的特定行为和操作。这些魔法函数可以让我们自定义对象的行为,例如实现对象的比较、算术运算、属性访问等。常见的魔法函数包括__init__(构造函数)、__str__(返回对象的字符串表示)、__add__(实现对象的加法运算)、__eq__(实现对象的相等比较)等。通过实现这些魔法函数,我们可以让我们的自定义对象更加灵活和强大。

原本没有这个能力,把这个函数写出来就有了

1.2、比较操作

  • lt(self, other)定义小于号的行为:x < y

   比大小

  •    def __lt__():


  # 比大小
   def __lt__(self, other):
    return self.age < other.age
 ​
 # 测试lt
 d1 = Dog1(age=20)
 d2 = Dog1(age=18)
 d3 = Dog1(age=19)
 print(d1 < d2)  # 答案False
  • le(self, other)定义小于等于号的行为:x <= y

  • eq(self, other)定义等于号的行为:x == y

  • ne(self, other)定义不等号的行为:x != y

  • gt(self, other)定义大于号的行为:x > y

  • ge(self, other)定义大于等于号的行为:x >= y

1.3、常见的魔法函数

  • 初始化def __init__(): 

 class Dog:
     namee: str
     age: int

 ​
     
 # 初始化(相当于Java里面的构造函数)
   def __init__(self, namee='hhh', age=18):
       self.namee = namee
       self.age = age


 # 测试init传不传参数
 #new一个出来Dog
  d1 = Dog('jack',19)#必须传两个参数,因为初始化上有两个,否则报错

 #如果只想传一个就用默认值
  d1.Dog(age=20)#传了一个它自己self
 ​

通过关键字传参,指定传参 


 d1 = Dog1(age=20)
 print(d1)  # 是对象@。。。,显示用tosting一样 

输出对象 

没有重载 ,如果即想要有参有想要无参,只能传默认值(希望某个值不填)

  class Dog:
     name: str
     age: int


#不能前面有后面没有(name和age都要有)
def __init__(self, name='', age=18):
         self.name = name
         self.age = age

d1=Dog()

必须带参数因为初始化上有两个,否则报错 

  • def __str__(self): 

   相当于toString
  

  class Dog:
     name: str
     age: int
 

  def __str__(self):
         return f'{self.namee},{self.age}'


# 测试str
d1 = Dog(age=20)
print(d1)  # 是对象@。。。,显示用tosting一样

  •    def __bool__(self):

  bool 可用于逻辑判断部分

​
 ​
   def __bool__(self):
       return self.age > 18
       
     
 #测试bool
 print(bool(T(17) and T(19)))  

​

  •  def __call__():

允许一个类的实例像函数一样被调用,可以把类当成装饰器使用

class Dog:
  def __call__(self, *args, **kwargs):
       print("类的实例可以像函数一样被调用")

 # 测试call
  d1=Dog1(age=20)
#多了个括号
 d1()


  •      def __del__(self):

  del 是析构方法,当对象的引用计数变为0时,这个对象会被销毁掉,可以用用于关闭资源



  #del 是析构方法,当对象的引用计数变为0时,这个对象会被销毁掉,可以用用于关闭资源
     def __del__(self):
         print("对象被销毁")      
         
 #测试del
 t = Dog1()
 # t指向0,此前创建的T的实例被销毁
 t = 0
         
 ​
  •      def __len__(self): 

 len 是内置函数,len(t) 会调用实例的 len 方法,len一般用在集合中,如果想测量狗,就要重写len

class Dog:
def __len__(self):
return 100

d1 = Dog()
print(len(d1))

1.4、属性管理

属性寻找规则: 先找实例的 dict ,再去查找类的 dict

class Plane(object) :
   #类属性
   categoryf='飞机'

# 实例化两个飞机,categoryf飞机种类
 p1, p2 = Plane('ccc'), Plane('bb')
 #把类改了
 Plane.category = '拖拉机'
 print(f'{p1.category},{p2.category}')
#输出:拖拉机,拖拉机

 #p1重新赋值
 p1.category = '小飞机'
 print(f'{p1.category},{p2.category}')
 ​#输出:小飞机,拖拉机

 #p1删除
 del p1.category
 print(f'{p1.category},{p2.category}')
 #输出:拖拉机,拖拉机



  ​原因:
 # 类对象里面有一个字典
 print(Plane.__dict__)
 # 实例化对象也有一个字典
 print(p1.__dict__)


 ​  总:两个里面都有category这个属性,优先拿自己的(在没有别人的情况下)

1.5、类属性与实例属性区分

class Plane(object) :
   #类属性
   categoryf='飞机'



def __init__(self, name):
       #实例属性
         self.name = name
        

 属性装在字典里面,所有还能例外方式赋值

把age直接给字典

p1.__dit__['age']=10

 python中对象的属性为什么可以动态变化?

类属性同样是存储在字典中,只是这个字典是类的字典 可以通过类名和对象名来调用,但是只能通过类名修改,类属性对于该类对象是共享的 类的属性和方法存在在类的 dict 之中

二、封装

2.1、概念:

(对属性做限制,封装若有若无)

使用一个下划线就等于向使用者宣布这个属性是私有的,但你仍然可以直接对其修改,单个 下划线更像是一种约定,而非技术上的强硬限制。即便使用了双下划线,也仍然有办法直接对其修改, 但这已经不是类所要解决的问题了,一个人执意破坏数据,他总是能找到办法。

 __强制

2.2、封装方式

封装方式一: 

 class Cat:
     #私有化
     __age: int  # __强制
 ​
     def __init__(self, age):
         self.__age = age

            
             
 #会找不到,因为私有化了,要get set
 c1 = Cat(19)
 print(c1.__age)也不能这样调


 #正确调法
 c1.set_age(30)
 print(c1.get_age())
 ​   
 ​
 #方法一
  #get set
  def get_age(self,age):
      return  self.__age
 ​
  def set_age(self,age):
       if age >20:
            print('死了')
       else:
            self.__age=age
             
 ​
 #测试  没有get和set强行修改,也可以修改的__dict__
 c1 = Cat(19)
 #直接改字典
 print(c1.__dict__)
 ​

封装方式二

​
 ​
 # 封装方法2(装饰器)
 class Pig:
     #私有化
     __age: int  # __强制
 ​
     def __init__(self, age):
         self.__age = age
 ​
 ​
 ​   #装饰器
     @property
     def age(self):
         return self.__age
 ​
 ​
     @age.setter
     def age(self,age):
         self.__age= age
         

 

         
        
 ​


 

 两个封装区别

方式一如果想添加代码就要一个一个加,因为不同地方调用了那个方法,方式二就不用
 ​使用 @property 装饰器修饰 方法后,你就可以像使用属性一样使用 某个属性  ,如果你希望可以对 某个属性进行赋值,那么需要用 @ 某个属性.setter 装饰器再装饰一个方法,该方法完成对 属性的赋值操 作。

我们认为自己直接操作了对象的属性,但其实我们是在使用类的方法,而且关键的是省去了调用方法时 的那对小括号
 ​ 

2.3、方法拓展

  
  类方法可以用类名调用
   #类方法
     @classmethod
     def run(cls):
         #可以操作类属性,不能操作对象属性因为没有self
         print(cls.__age)
#用类调用

 Pig.run()


     #静态方法,什么东西都没带,不能类属性也不能调对象属性,只是单纯函数而已
     @staticmethod
     def say():
         print("hello world")
         

三、继承

3.1、概念

如果没有指定基类,会默认继承 object 类, object 是所有类的基类,它提供了一些常见方法

3.2、语法

class Dog(多个父类,就进原则,如果是obj可以默认不写):

3.3、区别

类属性Dog.xx 实例属性self.xx

类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类

class Dog:
    pass

class Cat:
    pass


#一个父亲一个母亲
class Lion(Dog, Cat):
    pass

 查看继承谁

#方式一:__bases__ 
print(Lion.__bases__)

#方式二:__mro__ 更详细
 print(Lion.__mro__)

跟谁亲,就近原则 

场景:在一个类要实现多个类,可以产生方法冲突

class Lion(Dog, Cat):
    pass

 
class Dog:
     food:'叭叭叭'
     def say(self):
         print('我要吃'+self.food)
 ​
 ​
 class Cat:
 ​
     food='yyyyy'
 ​
     def say(self):
         print('我要吃' + self.food)
 ​

#希望调父类方法:

 #调用错误的 ----不能用类去调,say是对象
 print(Lion.say())

 #正确的
 Lion().say()
 print(Lion.food)
 ​

四·、多态

4.1、概念:

在一个时期有不同的状态

#动物类
class Animal(object):
    #表演的方法
    def play(self):
        pass

#老虎类继承了动物类
class Tiger(Animal):
    #重写方法
    def play(self):
        print("正在表演老虎吃人")

#狮子类继承了动物类
class Lion(Animal):
    def play(self):
        print("正在表演狮子跳火圈")

#人类与
class Person(object):
    #与动物玩耍
    def show(self, a: Animal):
        print("动物开始表演了")
        a.play()


p = Person()
#一个老虎
tiger = Tiger()
#一个狮子
lion = Lion()

谁表演

# 让老虎表演
p.show(tiger)
# 让狮子表演
p.show(lion)

五、模块(Python文件)

在Java习惯:不同作用的类放在一起,形成包 --->导包

 导入模块=相当于Alt+/

5.1、概念:

Python 模块(Module),是一个 Python 文件,以 .py 结尾,包含了 Python 对象定义和Python语句。 模块让你能够有逻辑地组织你的 Python 代码段。 把相关的代码分配到一个模块里能让你的代码更好用,更易懂。 模块能定义函数,类和变量,模块里也能包含可执行的代码

5.2、语法:

  import  modu

5.3不同方式导模块

 #方法一导入全部方法 取个别名
  import  modu as m
  m.p()
 m.hello()
 ​
 #方法二单独某个方法
  from modu import hello,P
  hello()
  P()
 #方法三单独一个方法取个别名
  from modu import  hello as h
  h()
 ​
 #方法四导全部,但是是自己想要给别人的全部
  from modu import *
  P()
 搭配 __all__ = [] 使用



#另外一个页面
 __all__ = ['Cat']

Class Cat:
    pass

def hello():

5.4、导入包

 import package.module
 import package.module as xx
 from package.module import xx
 from package.module import xx as xx
 ​
 ​
 #导包
 #方法一要 包名点类名取别名
  import soud.s1 as s
  s.say1()
 ​
 #方法二要在init里面写all
 from soud import  *
 s1
 搭配 __init__.py中的__all__ = [] 使用

六、标准模块collections

collections实现了许多特定容器,这些容器在某些情况下可以替代内置容器 dict, list, tuple, set, 原因 在于,他们提供了在某个方面更加强大的功能。

6.1、Counter 统计对象的个数

数据太多,可以计算它每个字母出现的次数

 keys = "Hold fast,and let go;" \
    "understand this paradox," \
    "and you stand at the very gate of wisdom."
 cs = Counter(keys)
 print(cs)

\回车代表换行

6.2、ChainMap 合并多个字典,还可以用**

 dic1 = {'python': 100}
 dic2 = {'java': 99}
 cm = ChainMap(dic1, dic2)
 cm = dict(cm)#转字典
 print(cm)

6.3、OrderedDict 有序字典 (3.6之后字典自带)

6.4、defaultdict默认字典

不会引发KeyError的字典,如果拿一个没有的会报错,它可以使它不报错返回0 在创建这种字典时,必须传入一个工厂函数,比如int, float, list, set。defaultdict内部有一个 missing(key) 方法,当key不存在时,defaultdict会调用 missing 方法根据你所传入的工厂函数返回一个默认值。你传入的工厂函数是int,那么返回的就是0, 如果传入的是list,返回的就是空列表

 d1={
    "java":100,
    "python":99
 }
 print(d1['c++'])#没有c++这个课程,报错,但是有时候我们不希望它报错


 ​
 eg:
 #指定类型
 dic = defaultdict(int)
 dic['a'] = 1
 dic['b'] = 2
 dic['c'] = 3
 print(dic['f'])

6.5、deque 一个类似列表的容器

栈就相当于客栈:先进后出

队列相当于排队:先进先出

方法

  • 类似列表的容器,支持在两端快速的追加和删除元素。

  • append (在末尾追加数据)

  • appendleft (在头部追加数据)

  • pop (删除并返回指定索引的数据,默认是末尾数据)

  • popleft(删除并返回头部数据)

  • insert(在指定位置插入数据)

  • remove(删除指定数据)

七、functools函数工具

7.1、singledispatch 单处理的泛型函数(单个调动)

 #以前写法
#学生类
 class Stu(object):
  def wake_up(self):
    print('起床')
 ​
#警察类
 class Police:
  def wake_up(self):
    print('起床')

#new了一个学生一个警察 ​
 stu = Stu()
 police = Police()

 ​
 def wake_up(obj):
#isinstance判断某个类是不是它的子类
  if isinstance(obj, Stu):
    print('今天周末休息,让孩子们再睡一会')
  elif isinstance(obj, Police):
    print('警察很辛苦,又要起床了')
    obj.wake_up()
  else:
    print('不处理')
 ​
 wake_up(stu)
 wake_up(police)
 wake_up('一个字符串')
 ​



 #现在写法
 ​
 
 from functools import singledispatch
 ​
 class Stu(object):
  def wake_up(self):
    print('起床')
 ​
 class Police:
  def wake_up(self):
    print('起床')
 ​
 stu = Stu()
 police = Police()
 ​

#装饰器
 @singledispatch
 def wake_up(obj):
  print('不处理')
 ​
 @wake_up.register(Stu)
 def wake_stu(obj):
  print('今天周末休息,让孩子们再睡一会')
 ​
 @wake_up.register(Police)
 def wake_police(obj):
  print('警察很辛苦,又要起床了')
 ​
  obj.wake_up()
 wake_up(stu)
 wake_police(police)
 wake_up('一个字符串')

7.2、wraps 装饰器修饰

python标准模块functools提供的wraps函数可以让被装饰器装饰以后的函数保留原有的函数信息,包括 函数的名称和函数的注释doc信息。

#做成了装饰器
def hello(func):
    #加了这个装饰器以后输出say
    @wraps(func)
    def inner():
        pass

    return inner



@hello
def say():
    pass


#输出inner,就比如是答非所问了
point(say. __name__)

7.3、reduce 规约函数

reduce(对集合做操作)的作用是从左到右对一个序列的项累计地应用有两个参数的函数,以此合并序列到一个单一值,简单来说就是把集合合成一个整体

与filter()过滤、map()一样的集合做操作,reduce要导包

计算1-100的和


 reduce(lambda a,b:a+b,range(1,100))#1,2,3,4....
 ​
 #a第一次是1,b为2 a+b=3
 #a第二次是3 b是后面那个就是3
 ​

 ​

相加起来拼成一个字符串

 ns=[{"name":"a"},{"name":"b"},{"name":"c"}]
 #字符串后面加个空字符串
 print(reduce(lambda a,b:a+b['name'],ns,""))
 #int后面加个0
 print(reduce(lambda a,b:a+b['age'],ns,0))

八、异常

8.1、.抓异常try

 try:
    print(1 / 0)
 except Exception as e:#分母不能为0
    print(e)
 else:
  print('no error')#没异常出
 finally:
  print('close')#不管有没有异常都出来

8.2、自定义异常类 raise抛出异常


 try:
  raise TypeException('类型不匹配')
 except Exception as e:
  print(e)
 ​
 ​
 ​
 def eat(obj):
     #方法一raise
     if isinstance(obj,str):
         pass
     else:
         raise Exception("类型不是我想要的")
       #方法二断言assert
     assert isinstance(obj str),"类型不符合"
     
 eat(123)        

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1336191.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

WPS复选框里打对号,显示小太阳或粗黑圆圈的问题解决方法

问题描述 WPS是时下最流行的字处理软件之一&#xff0c;是目前唯一可以和微软office办公套件相抗衡的国产软件。然而&#xff0c;在使用WPS的过程中也会出现一些莫名其妙的错误&#xff0c;如利用WPS打开docx文件时&#xff0c;如果文件包含复选框&#xff0c;经常会出…

博客摘录「 Apollo安装和基本使用」2023年11月27日

一、常见配置中心对比 Spring Cloud Config: https://github.com/spring-cloud/spring-cloud-configApollo: https://github.com/ctripcorp/apolloNacos: https://github.com/alibaba/nacos 对比项目/配置中心 spring cloud config apollo nacos(重点) 开源时间 2014.9 …

blender scripting 编写

blender scripting 编写 一、查看ui按钮对应的代码二、查看或修改对象名称三、案例&#xff1a;渲染多张图片并导出对应的相机参数 一、查看ui按钮对应的代码 二、查看或修改对象名称 三、案例&#xff1a;渲染多张图片并导出对应的相机参数 注&#xff1a;通过ui交互都设置好…

如何在Window系统下搭建Nginx服务器环境并部署前端项目

1.下载并安装Nginx 在nginx官网nginx: download 下载稳定版本至自己想要的目录。 解压后进入目录 2.启动Nginx服务器 启动方式有两种&#xff1a; &#xff08;1&#xff09;直接进入nginx安装目录下&#xff0c;双击nginx.exe运行&#xff0c;此时命令行窗口一闪而过&…

20231222给NanoPC-T4(RK3399)开发板的适配Android11的挖掘机方案并跑通AP6398SV

20231222给NanoPC-T4(RK3399)开发板的适配Android11的挖掘机方案并跑通AP6398SV 2023/12/22 7:54 简略步骤&#xff1a;rootrootrootroot-X99-Turbo:~/3TB$ cat Android11.0.tar.bz2.a* > Android11.0.tar.bz2 rootrootrootroot-X99-Turbo:~/3TB$ tar jxvf Android11.0.tar.…

【MySQL】数据库中为什么使用B+树不用B树

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a; 数 据 库 ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 前言 正文 B树的特点和应用场景&#xff1a; B树相对于B树的优势&#xff1a; 结论&#xff1a; 结语 我的其他博客 前言 在数据…

超维空间S2无人机使用说明书——31、使用yolov8进行目标识别

引言&#xff1a;为了提高yolo识别的质量&#xff0c;提高了yolo的版本&#xff0c;改用yolov8进行物体识别&#xff0c;同时系统兼容了低版本的yolo&#xff0c;包括基于C的yolov3和yolov4&#xff0c;以及yolov7。 简介&#xff0c;为了提高识别速度&#xff0c;系统采用了G…

C# WPF上位机开发(子窗口通知父窗口更新进度)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 这两天在编写代码的时候&#xff0c;正好遇到一个棘手的问题&#xff0c;解决之后感觉挺有意义的&#xff0c;所以先用blog记录一下&#xff0c;后…

数组基础及相关例题

目录 1.一维数组的初始化 2.二维数组的初始化 3.字符数组 1.puts 2.gets 3.strcat 4.strcpy 5.strcmp 6.strlen ​编辑 7. strlwr与strupr 易错习题 1 2 3 4 5 6 1.一维数组的初始化 2.二维数组的初始化 注意 第一维的长度不用指定&#xff0c;第二维的…

WU反走样算法

WU反走样算法 由离散量表示连续量而引起的失真称为走样&#xff0c;用于减轻走样现象的技术成为反走样&#xff0c;游戏中称为抗锯齿。走样是连续图形离散为想想点后引起的失真&#xff0c;真实像素面积不为 零。走样是光栅扫描显示器的一种固有现象&#xff0c;只能减轻&…

FPGA分频电路设计(2)

实验要求&#xff1a; 采用 4 个开关以二进制形式设定分频系数&#xff08;0-10&#xff09;&#xff0c;实现对已知信号的分频。 类似实验我之前做过一次&#xff0c;但那次的方法实在是太笨了&#xff1a; 利用VHDL实现一定系数范围内的信号分频电路 需要重做以便将来应对更…

B+树索引和哈希索引的区别?

B树是一个平衡的多叉树&#xff0c;从根节点到每个叶子节点的高度差值不超过1&#xff0c;而且同层级的节点间有指针相互链接&#xff0c;是有序的&#xff0c;如下图&#xff1a; 哈希索引就是采用一定的哈希算法&#xff0c;把键值换算成新的哈希值&#xff0c;检索时不需要类…

STM32独立看门狗

时钟频率 40KHZ 看门狗简介 STM32F10xxx 内置两个看门狗&#xff0c;提供了更高的安全性、时间的精确性和使用的灵活性。两个看 门狗设备 ( 独立看门狗和窗口看门狗 ) 可用来检测和解决由软件错误引起的故障&#xff1b;当计数器达到给 定的超时值时&#xff0c;触发一个中…

MyBatis中select语句中使用String[]数组作为参数

&#x1f607;作者介绍&#xff1a;一个有梦想、有理想、有目标的&#xff0c;且渴望能够学有所成的追梦人。 &#x1f386;学习格言&#xff1a;不读书的人,思想就会停止。——狄德罗 ⛪️个人主页&#xff1a;进入博主主页 &#x1f5fc;专栏系列&#xff1a;无 &#x1f33c…

CMakeLists.txt

源码结构 生成可执行程序 # CMake最小版本号 cmake_minimum_required(VERSION 3.15.0)#增加-stdc11 set(CMAKE_CXX_STANDARD 11)#设置工程名称 project(calculate)#[[ #方法一&#xff1a;添加源码文件 #aux_source_directory(< dir > < variable >) #dir&#xf…

Netty组件基础

Netty入门简介 netty是一个异步、基于事件驱动的网络应用框架&#xff0c;用于快速开发可维护、高性能的网络服务器和客户端。 Netty优势 Netty解决了TCP传输问题&#xff0c;如黏包、半包问题&#xff0c;解决了epoll空轮询导致CPU100%的问题。并且Netty对API进行增强&#xf…

Github 2023-12-26开源项目日报 Top10

根据Github Trendings的统计&#xff0c;今日(2023-12-26统计)共有10个项目上榜。根据开发语言中项目的数量&#xff0c;汇总情况如下&#xff1a; 开发语言项目数量Python项目7非开发语言项目1JavaScript项目1TypeScript项目1 GPT PILOT: 从头开始编写可扩展的应用程序的开发…

MVC下的四种验证编程方式

ASP.NET MVC采用Model绑定为目标Action生成了相应的参数列表&#xff0c;但是在真正执行目标Action方法之前&#xff0c;还需要对绑定的参数实施验证以确保其有效性&#xff0c;我们将针对参数的验证成为Model绑定。总地来说&#xff0c;我们可以采用4种不同的编程模式来进行针…

北亚服务器数据恢复-服务器断电导致raid5故障的数据恢复案例

服务器数据恢复环境&#xff1a; 服务器有一组由12块硬盘组建的raid5阵列。 服务器故障&分析&#xff1a; 机房供电不稳导致服务器意外断电&#xff0c;工作人员重启服务器后发现服务器无法正常使用。 根据故障情况&#xff0c;北亚企安数据恢复工程师初步判断服务器故障原…

【深度学习目标检测】十一、基于深度学习的电网绝缘子缺陷识别(python,目标检测,yolov8)

YOLOv8是一种物体检测算法&#xff0c;是YOLO系列算法的最新版本。 YOLO&#xff08;You Only Look Once&#xff09;是一种实时物体检测算法&#xff0c;其优势在于快速且准确的检测结果。YOLOv8在之前的版本基础上进行了一系列改进和优化&#xff0c;提高了检测速度和准确性。…