定义类:
如果函数在类中,那么称之为类方法
class Student: def study(self ,course): print(f"该学生在学{course}") def play(self): print("该学生在玩") s1=Student() s2=Student() s1.study("python") s1.play() Student().study("java")#调用当前类中的方法,首先需要对当前的类进行实例化:类()创建类的属性和方法
class Student: def __init__(self,name,age):#创建默认值 self.name=name self.age=age def study(self,course): print(f"{self.name}正在学习{course}") def play(self): print(f"{self.name}正在玩") def __repr__(self):#__创建默认值 return f"{self.name}:{self.age}" s1=Student("周清",21) print(s1)#周清:21 s1.study("python")#周清正在学习python s1.play()#周清正在玩可见性和属性装饰器:
class Student(): def __init__(self,name,age): self._name=name#私有变量 self._age=age#私有变量 def study(self,course_name): print(f"{self._name}正在学习{course_name}") s1=Student("周清",12) s1.study("python") #print(s1.__name)#没办法访问,私有属性property:为私有属性提供读取和修改的方法
class Student(): def __init__(self,name,age): self._name=name#私有变量 self._age=age#私有变量 #获取私有属性 @property def name(self): return self._name #修改私有属性 @name.setter def name(self,name): self._name=name or "无名氏" #获取私有变量 @property def age(self): return self._age def study(self,course_name): print(f"{self._name}正在学习{course_name}") s1=Student("周清",12) print(s1.name,s1.age)#周清 12 s1.study("python")#周清正在学习python s1.name="123" print(s1.name) #123静态方法和类方法
静态方法:传入的参数都是普通的参数,不和当前的类进行绑定,可以看成一个单独的函数.
在调用静态方法时,不需要对当前类进行实例化,也就是创建对象
类方法:参数第一位必须是cls,代表当前的方法是属于当前的类
动态属性
class Student(): def __init__(self,name,age): self.name=name self.age=age stu=Student("周清",12) #添加一个属性 stu.sex="女" print(stu.name,stu.age,stu.sex)#周清 12 女当不想添加属性时,写入
__slots__=("name","age")这样sex就不能添加进去
class Student(): __slots__ = ('name', 'age') def __init__(self,name,age): self.name=name self.age=age stu=Student("周清",12) print(stu.name,stu.age)#周清 12继承:单继承,多继承
class 类名(父亲名):
pass
class Animal(): def eat(self): print("吃") def sleep(self): print("睡觉") class Dog(Animal): def speak(self): print("汪汪叫") dog=Dog() dog.eat() dog.speak()- 子类继承父类,可以直接享受父类中已经封装好的方法,不需要再次开发
- 子类中应该根据职责,封装子类特有的属性和方法
继承的传递性
方法的重写:
当父类的方法不能满足子类的要求
在进行方行子类中重写的方法
class Dog(Animal): def speak(self): print("汪汪叫") #方法的重写 def eat(self): print("吃骨头") dog=Dog() dog.eat()#吃骨头super:
def eat(self): print("吃骨头") super().eat()#吃,调用父类的 print('123')另外一种调用的方式,通过父类的名字调用
Animal.eat(self)父类的私有属性和私有方法:
- 子类对象不能在自己的方法内部,直接访问父类的私有属性和私有方法
- 子类对象可以通过父类的公有方法间接访问到私有属性和私有方法
class Animal(): def __init__(self): self.num1=100 #私有的变量 self.__num2=200 #私有的方法 def __func(self): print(f"{self.num1}+{self.__num2}") class Dog(Animal): def func1(self): super().func() pass dog=Dog() print(dog.num1) #print(dog.__num2)#会报错 dog.func1()#会报错访问父类的私有方法和私有属性
class A(): def __init__(self): self.num1=100 self.__num2=200 def __func(self): print(f"{self.num1}+{self.__num2}") def func1(self): print(f"{self.__num2}") self.__func() class B(A): def func2(self): print(f"{self.num1}") self.func1()#子类可以通过父类的公有方法间接访问到父类的私有属性和私有方法 b=B() b.func2()#100 #200 #100+200多继承:
class A(): def demo(self): print("demo方法") class B(): def test(self): print("test方法") class C(A,B): pass c=C() c.demo() c.test()如果在多继承的情况下发现父类中的方法有重名:尽量避免使用多继承
多态
不同的子类对象调用相同的父类方法,产生不同的执行结果
- 多态可以增加代码的灵活度
- 以继承和重写父类方法为前提
- 是调用方法的技巧,不会影响到类的内部设计
class Dog(): def __init__(self,name): self.name =name def play(self): print(f"{self.name}在玩耍") class Xiaotiandog(Dog): def play(self): print(f"{self.name}在天上飞") class Person(): def __init__(self,name): self.name =name def person_with_dog(self,dog): d.play() print(f"{self.name}和{dog.name}在一起玩耍") d=Xiaotiandog("旺财") xiaoming=Person("小明") xiaoming.person_with_dog(d)#旺财在天上飞 #小明和旺财在一起玩耍创建出来的对象叫做类的实例
类属性:
访问类属性有两种方式:
- 类名.类属性
- 对象.类属性(不推荐)
class Tool(): count=0 def __init__(self,name): self.name =name Tool.count+=1 tools=Tool("斧头") print(tools.count)#1 print(Tool.count)#1 tools.count=100 print(tools.count)#100 print(Tool.count)#1类方法:
需要用修饰符@classmethod来标识,告诉解释器这是一个类方法
class Tool(): sum=0 def __init__(self,name): self.name =name Tool.sum+=1 @classmethod def count(cls): print(f"类方式:{cls.sum}") def count1(self): print(self.sum) tools=Tool("hh") tools1=Tool("DGJS") Tool.count() tools.count1()静态方法:
当前方法不需要访问类属性和调用类方法,不需要访问实例属性和调用实例方法的情况下,封装成静态方法
class A: @staticmethod def func():#不需要写self print("小狗在跑") A.func()#直接用类调用单例设计模式:
目的——让类创建的对象,在系统中只有唯一的一个实例
每一次执行类名()返回的对象,内存地址是相同的
应用场景:音乐播放,回收站,打印机
_new_方法:
使用类名()创建对象时,Python的解释器首先会调用_new_方法为对象分配空间
重写_new_方法一定要return super()._new_(cls)
class Musicplay: def __new__(cls, *args, **kwargs):#父类的new方法已经实现了划分内存地址的代码 print("音乐")new return super().__new__(cls)#为对象分配空间,父类中的new方法是一个类方法 def __init__(self): print("音乐器播放音乐") musicplay=Musicplay()#音乐 #音乐器播放音乐Python中的单例:
class Musicplay: instance=None def __new__(cls, *args, **kwargs): if cls.instance is None: cls.instance=super().__new__(cls) return cls.instance music1=Musicplay() music2=Musicplay() print(music1)#<__main__.Musicplay object at 0x0000029FB35791C0> print(music2)#<__main__.Musicplay object at 0x0000029FB35791C0>,地址是一样的异常:
通过异常捕获可以针对突发事件做集中的处理,从而保证程序的稳定性和健壮性
try: num=int(input("请输入数字")) print(num) except: print("请输入一个整数")try: num=int(input("请输入数字")) result=8/num print(result) except ZeroDivisionError: print("请输入非0的数") except ValueError: print("请输入正确的整数") else: print("输入正确的数字,才会执行成功") finally: print("无论是否出现错误,都会执行")异常的传递:
def deno1(): return int(input("请输入一个整数")) def demo2(): return deno1() if __name__=="__main__": try: print(demo2()) except Exception as e: print(f"未知错误{e}")主动抛出异常
def get_password(): password=input("请输入密码") if len(password)>=8: return password #创建异常对象 ex=Exception("密码长度不够") # 主动抛出异常 raise ex if __name__=="__main__": try: print(get_password()) except Exception as e: print(f"{e}")