一、类
格式:class name() 、class name
class 作为关键字,后面跟上 类的名称 ,继承时使用括号,否则省略。
二、属性和方法
1.实例属性
类似变量,即生成实例时,需要传入的参数变量(初始化方法内定义参数变量) 或者无需定义 直接使用 实例.变量名称。
class Test: def __init__(self,j): self.j=j print(self.j) test01=Test(1000)#1000 test01.i=1 print(test01.i)#1 test01.i=2 print(test01.i)#2
2.实例方法
类似函数,实例方法的第一个参数必须是self (约定俗成)。使用方法为:实例.方法名称() 或者 类名称.方法(实例)
class Test: def eat(self): print(f'吃!') test01=Test() test01.eat() Test.eat(test01) class Test: def eat(self,food): self.food=food print(f'吃{self.food}!') test01=Test() test01.eat('小吃') Test.eat(test01,'小吃')
3.类属性
实例属性是必须跟随实例使用,但类属性不是,与类一样,属于”模板“中的一员。
class Test: sum =0 print(Test.sum) test01=Test() print(test01.sum)
4.类方法
需要使用 @classmethod
与实例方法类似,第一个参数为(cls)。
类方法不可以直接使用类属性和实例变量(但是可以使用 类名.实例名称 、cls.实例名称访问),但可以被类或类的实例直接调用
class Test: sum =0 def __init__(self, ls1): self.ls1=ls1 def js1(self,ls2): self.ls2 = ls2 @classmethod def js(cls): Test.sum+=1 cls.sum+=1 print(Test.sum,cls.sum) test01=Test('1') test01.js()
5.静态方法
需要使用 @staticmethod
不需要传入self实例参数和cls类参数
不可以访问实例属性,但可以访问类属性;可以被类和类实例调用
6.初始化方法
def __init__(self[, 形参列表]):
实例化时需要在类名后传入变量,第一个参数是 self(类似函数)
如果需要return语句返回,则必须返回None
二、继承
同1 ,在定义类的时候括号类添加父类名称,多个父类使用逗号相隔(单继承就是一个父类,多继承就是多个父类)。
class Animal: def eat(self,food): print(f"{self.kind}在吃{food}") class Dog(Animal): def run(self): print("狗在奔跑!") class Bird(Animal): def fly(self): print("鸟正在天上飞!") animal01=Animal() animal01.kind="狮子" animal01.eat("饭") dog01 =Dog() dog01.run() dog01.kind="狗" dog01.eat("骨头") bird01 =Bird() bird01.fly() bird01.kind="鸟" bird01.eat("虫")
继承能将方法全部继承,属性需要进行初始化函数才可以 :
def __init__(self,kind,price,c_rate,an):
Car.__init__(self,kind,price)
class Car: def __init__(self,kind,price): self.kind=kind self.price=price class Electric(Car): def __init__(self,kind,price,c_rate,an): Car.__init__(self,kind,price) self.c_rate =c_rate self.an=an print(f"牌子为{self.kind},价格为{self.price},充电速度为百分之{self.c_rate}每小时,容量为{self.an}") carl01=Car("小米",4000) electric=Electric("小米",4000,50,12)
若方法相同,按照子类、父类1、父类2的顺序获取方法;同名称,未被使用的方法,这种现象便是覆盖。
三、封装
隐藏类的细节,使用者无法像常规调用属性或方法那样使用。
双下划线__开头(属性和方法都是)
例如:定义父类A,存在一个私有属性和一个私有方法,一个公用方法在实例化之后,实例化对象只能调用公用方法(使用 a._A__f1() 也能强行使用私有方法, a._A__s1 强行使用属性),同理,在子类中也不能直接访问私有属性和私有方法。
class A: def __init__(self): self.__s1 = 100 # 私有属性 def __f1(self): # 私有方法 print("__m1(self) 方法被调用") def fA(self): self.__f1() print("self.__p1 = ", self.__s1) a= A()
四、多态
class Eat: def state(self): print("吃东西") class Play(): def state(self): print("玩游戏") def My_state(s): s.state() # 此处显示出多态 eat1 = Eat() play1 = Play() My_state(eat1) # 调用Circle 类中的draw My_state(play1) # Point 类中的draw
声明一个函数,此函数能传递不同实例得到不同结果,就是多态。
五、方法重写
若父类方法的功能不能满足需求时,可以在子类重写父类的方法(预定义的函数也是父类方法)。
例如 加法(add):x+y 得到 x和y两个变量的数值相加。若存在一组向量 a(1,2,3),向量b(3,4,5),加法不能实现对应位置相加,那么就得进行改写(使子类使用这个符号达到复杂的相加,而外部使用还是原本的相加):
x,y=5,5 print(x+y) # 10 class my_add(): def __init__(self, a): "构造函数,初始化MyNumber对象" self.a = a self.z= tuple() def __add__(self, rhs): if len(self.a)>=len(rhs.a): c = len(self.a)-len(rhs.a) rhs.a += (0,)*c else: c = 0-len(self.a) - len(rhs.a) self.a += (0,) * c for i in range(0,len(self.a)): self.z+=(self.a[i]+rhs.a[i],) return self.z x1=1,2,3 y1=4,5,6 a1=my_add(x1) b1=my_add(y1) print(a1+b1) #(5, 7, 9) 对应位置相加 print(x1+y1) #(1, 2, 3, 4, 5, 6) 元组普通加法l
六、super
1、super 方法
在子类继承父类(单个),可能造成覆盖,导致父类方法失效,在子类中可以使用 super().方法名称()使用该方法(名称.方法 会报错),在外部中可以从子类实例调用方法(seper(子类名称,子类实例对象).父类方法名称):
class F: # 定义父类 def fun(self): print('父类方法') class C(F): # 定义子类 def fun(self): super().fun() #子类调用父类方法 print('子类方法') c = C() # 外部子类实例 c.fun() # 外部子类调用子类方法 super(C,c).fun() # 外部子类调用父类方法
2、super().init()
super().__init__()
继承父类构造函数,继承其属性内容(若属性有默认值,那么可以选择不写。若没有,则一定要写),也可以使用 父类名称.__init__()
class F: # 定义父类 def __init__(self,name,age): self.name = name self.age = age return self .name class C(F): # 定义子类 def __init__(self,name,age): super().__init__(name,age) print(f"{self.name},{self.age}") c = C("小黑",15) # 外部子类实例
class F: # 定义父类 def __init__(self,name,age=0): self.name = name self.age = age return self .name class C(F): # 定义子类 def __init__(self,name): super().__init__(name) print(f"{self.name},{self.age}") c = C("小黑") # 外部子类实例
class F: # 定义父类 def __init__(self,name,age=0): self.name = name self.age = age return self .name class C(F): # 定义子类 def __init__(self,name,age): super().__init__(name) print(f"{self.name},{age}") c = C("小黑",5) # 外部子类实例
3、钻石继承
当多重继承时,不断对父类进行改写,对最后子类调用父类时,相同方法对父类调用了多次。
class A: def fun(self): print("A被使用了") class B(A): def fun(self): print("B被使用了") A.fun(self) class C(A): def fun(self): print("C被使用了") A.fun(self) class D(B,C): def fun(self): print("D被使用了") B.fun(self) C.fun(self) d=D() d.fun()#D被使用了
#B被使用了
#A被使用了
#C被使用了
#A被使用了
class A: def fun(self): print("A被使用了") class B(A): def fun(self): print("B被使用了") super().fun() class C(A): def fun(self): print("C被使用了") super().fun() class D(B,C): def fun(self): print("D被使用了") super().fun() d=D() d.fun()#D被使用了
#B被使用了
#C被使用了
#A被使用了