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

目录

一、魔法函数

1.1、概念:

1.2、比较操作

1.3、常见的魔法函数

初始化def __init__(): 

def __str__(self): 

   def __bool__(self):

 def __call__():

     def __del__(self):

     def __len__(self): 

1.4、属性管理

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

二、封装

2.1、概念:

2.2、封装方式

封装方式一: 

封装方式二

2.3、方法拓展

三、继承

3.1、概念

3.2、语法:

四·、多态

4.1、概念:

五、模块(Python文件)

5.1、概念:

5.2、语法:

5.3不同方式导模块

5.4、导入包

六、标准模块collections

6.1、Counter 统计对象的个数

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

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

6.4、defaultdict默认字典

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

七、functools函数工具

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

7.2、wraps 装饰器修饰

7.3、reduce 规约函数

相加起来拼成一个字符串

八、异常

8.1、.抓异常try

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


一、魔法函数

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)        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

桃花坞生动的芒果

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

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

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

打赏作者

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

抵扣说明:

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

余额充值