python中类

前言:

继承是面向对象语言(比如 C++、python)中非常强大的功能,能大幅减少代码量,接下来,我们来了解一下 PythonPythonPython 中类的继承。(不是 Py 党的可以先去看一下:Python快速入门,特别详细)

前置知识——类

就算你不是个 Py 党,你应该也知道类是个什么。简单概括就是,他是我们定义的,用来定义对象的新类型(有点绕),与此同时,用这个类定义变量的过程叫类的实例化。接下来,为了方便讲述,我们把用这个类定义出来的变量叫这个类的实例

首先看如何定义一个类:

class A:

之后在下面就可以写对这个类的描述了(注意缩进)

接下来看如何定义一个类的属性。

因为类本质上是一个新类型,所以我们在类中的定义如果想作用到它的实例中去,我们定义的每个属性就必须针对那个实例(这或许是废话),但在类中,我们并不知道接下来要用这个类定义的实例叫什么,怎么针对呢?

其实,这就要到函数里去操作…

论 PythonPythonPython 类中的函数

与平常定义没啥区别,只不过当这个参数针对实例时,第一个参数所代表的是实例 ,这样你的函数才能对实例起作用。比如说: (我们为了叙述方便,暂且固定第一个参数名为 self)

class A:
    def vall(self,a):
        self.val=a

#假设前文定义了个实例d
#则 vall 可以这么用:
d.vall(1)    #把实例放在句点前
            #不知道句点用法的可以去看开头的链接
# 其实也还可以这么用

A.vall(d,1)  #或许这样更好理解

然后, PythonPythonPython 类规定了, init() 为构造函数(两旁各有两个下划线),可以往里传参,如果该函数针对实例,第一个参数必为 self (在类外不用给它传参,类外从函数模板中第二个参数开始传参),像这样:

class A:
    def __init__(self,a,c):
    self.a=a 
    self.b="name"
    self.c=c

#ta是这样用的
d=A(1,2)   #d为一个类的实例,1和2为两个参数,分别被赋给 self.a 和 self.c

之后总结一下再类外怎么用类里的函数:

构造函数: 实例 = 类名(构造函数的各个参数)

普通的,针对对象的变量或函数: 实例.函数+(参数…)/变量名

注:这里的参数不包括指代实例的名字

或 类名.函数(参数…)

注:这里的参数包括实例本身。

(为什么针对实例的变量不能这样写呢?因为变量只有通过句点才能让编译器明白它针对实例)

不针对对象的变量或函数: 类名.函数+(参数…)/变量名

这里举一个类的例子:

class A: 
    number=0    #定义不针对实例的变量

    def __init__(self,name,age):       #定义构造函数
        self.name=name
        self.age=age
        A.number+=1    #在类中也要把 'A.' 带上,否则number 会被解释器作为局部变量(这是 python 古老的特性)
    def bark(self):    #类中方法
        print(self.name,self.age)

dog=A("Tom",11)    #构造函数在一开始自动被使用,参数在括号里传
A.bark(dog) #调用方法
print(A.number)   #不针对实例的变量的调用

#输出

Tom 11
1

接下来讲继承部分

继承,就是在一个类中沿用另一个类中的对象(变量、函数…等等等等,在类里的都是)。被继承的叫“父类”“基类”“超类”,继承的叫“子类”“派生类”。一个类可以有多个父类,父类和子类间必须为从属关系。

先来看一下继承的语法,非常简单:

class 子类名(父类名):

就像刚刚所说的那样,子类沿用了父类的所有对象,如果子类中没有定义构造函数,将自动应用基类中的构造函数。同样,基类中已经实现的非私有(这个概念等会再说)的方法也可以被继承。

For example,

class A:    #定义父类
    def __init__(self,name):    #父类构造函数
        self.name=name
        self.num=1

class B(A):
     def numm(self):    #子类独有的方法
         print(self.num,self.name)

C=B("name")     #沿用父类的构造函数
C.numm()

#输出
1 name

子类中也可以引用父类中的变量:

class A:
    def __init__(self,name):
        self.name=name
        self.age=11

class B(A):
    def printf(self):   
        print(self.name,self.age)   #沿用父类中的 name 和 age

c=B("ttt")    #沿用父类构造函数

print(c.name)     #沿用父类中的 name

#输出
ttt

上面讲的是子类没有构造函数的情况,那如果有构造函数呢?

如果直接定义 init() ,那就只是个简单的重写了,就没法通过父类的构造函数来初始化实例了。 所以,打构造函数时,要先继承,再构造,这样才能获取父类的变量和继承其构造方法。

举个例子:

class A:
    def __init__(self,name,age):    #父类构造函数
        self.name=name
        self.age=age

    def tell(self): 
        print(self.name,self.age)

class B(A):
    def __init__(self,name,age,val):   
        A.__init__(self,name,age)  #这一步为继承
        self.val=val    #这是子类独有的构造部分

从上面可以看到,继承父类构造函数的语法是:

父类.init(self,…)

当然,方法不止这一种,想知道其他方法的可以去搜super关键字。

那为什么这里运用上了类似普通类中函数的调用语法呢?因为这里的实例是已经在函数模板指定了名字(即第一个参数的名字),所以可以用上类似普通类中函数调用的语法,而不用担心未定义的问题(用这种语法也可以区别父类和子类的构造函数,让解释器不迷茫)。

子类对父类方法的重写:

在子类中,如果我们想重写父类中的方法,让其在子类中有其他的意义,那该怎么办呢? 直接在子类中写就好。

class A:
    def __init__(self,name):    #父类构造函数
        self.name=name
        self.age=11 
    def tell(self):      #等着被重写的方法
        print("Hello!My name is %s."%self.name)
class B(A):
     def __init__(self,name,age):   #构造函数也被重写了
         self.name=name
         self.age=age
     def tell(self):   #重写 tell
         print("Hello!My name is %s and I am %d years old."%(self.name,self.age))

t1=A("ttt")
t2=B("kkk",17)    #两个实例

t1.tell()
t2.tell()

#输出
Hello!My name is ttt.
Hello!My name is kkk and I am 17 years old.

这里重写了构造函数和 tell 方法(当父类的构造函数对子类而言需求不大时可以不继承),所以要重写时直接写就好。

接下来给大家放一个类继承的例子:

class Person:      #基类
    def __init__(self,name,age,money):     #基类构造函数
        self.name=name
        self.age=age
        self.money=money

    def tell(self):           #基类方法
        print("I am %s,and I am %d year old."%(self.name,self.age))

    def give_money(self,to,money):    #同 tell ,基类方法
        self.money-=money
        to.money+=money

class teacher(Person):
    def __init__(self,name,age,money,stu=[]):
        Person.__init__(self,name,age,money)   #继承基类的构造函数
        self.students=stu   #独有构造部分

    def tell(self):      #重构 tell 方法
        print("I am teacher %s,and I am %d year old."%(self.name,self.age))
        print("I have %d students."%len(self.students))
        print("They are",end=' ')
        for i in self.students:   #迭代学生
            print(i.name+',',end='')
        print()
        print("And now I have ¥%d"%(self.money))   #沿用基类中的 money
    def give(self,money):      #子类中独有的函数
        t=money//len(self.students)
        self.money-=t*len(self.students)
        for i in self.students:
            i.money+=t

class student(Person):
    def __init__(self,name,age,money,tt=None):
        Person.__init__(self,name,age,money)   #继承构造函数
        self.teacher=tt   #子类独有构造部分

    def get_teacher(self,teacherr):    #子类对基类的拓展(即子类独有的方法)
        self.teacher=teacherr
        teacherr.students.append(self)

    def give_xuefei(self,to,money):    
        self.give_money(to,money)   #这里无需再次编写,直接引用父类中的方法

p1=teacher("Wu",34,20000)
p2=student("Z",12,13000)
p3=student("H",13,15000)   #三个实例
p2.get_teacher(p1)
p3.get_teacher(p1)     #两个学生拜师
p2.give_xuefei(p1,5000)   #p2 给学费
p1.tell()   打印 p1 的情况

#输出
I am teacher Wu,and I am 34 year old.
I have 2 students.
They are Z,H,
And now I have ¥25000

类继承例子二:AC自动机

之后来说一下之前留下来的疑问:私有方法

在类中,方法(即函数)分为三种:

1、特殊方法:被 PythonPythonPython 指定,拥有特殊作用的方法,拥有固定的作用,比如 init() 或 new() 为构造函数。重载运算符也靠此类方法(在例子二中有体现)。

2、私有方法:这些方法只能在类中被访问,在类外不能被访问,也不能被继承,在子类中用父类的私有方法会报错,定义方法为: def __函数名(各种参数) (左侧为两个下划线),调用的时候也要有这两个下划线

(但是,函数在 python 中,严格意义上也是对象,对象就能被复制,所以,你可以用一个公有方法去替代这个私有方法的功能,所以,私有方法并不是说完全不能访问,只是不能直呼其名)

(根据他人的提醒和自己的试验,私有方法之所以私有,是因为他的名字在访问时被突然改变了,而这种改变是有规律的,找到规律即可访问私有方法。这进一步地说明,python中没有什么是绝对私有的)

3、普通的公开方法,可以在类外调用,可以被继承。

类中变量的分类与此相似。(私有变量同私有方法一样,可以通过可变类型的引用改变其值,这里不多说)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值