初学者必看——详解python中类(class)创建和继承的相关问题


前言

类(class)被用于表示和模拟现实中的事物,相当于一个模板,由相同的类创建的实例具有相同的属性和功能,通常被用于面向对象编程

一、类的基本知识

1.创建类

#下面的例子来自于python编程:从入门到实践
class Dog():
	def __init__(self, name, age): """初始化属性name和age"""
		self.name = name 
		self.age = age
	def sit(self): """模拟小狗被命令时蹲下"""
		print(self.name.title() + " is now sitting.")
	def roll_over(self): """模拟小狗被命令时打滚"""
		print(self.name.title() + " rolled over!")
  • 和定义函数类似,用class来定义一个类,类的名字需要用驼峰式命名法如Dog,StudentOfClass)

  • 在类的内部,用def 来定义这个类拥有的函数,不过类中的函数通常被称为方法

  • class的方法分为两种,一种是__init__()方法,一种是其他的方法。第一种__init__()方法被用来定义类所拥有的属性(attribute),如上面例子中的self.name和self.age即为类的两个属性

  • 对于 __ init__()括号中的形参包括self形参和其他的形参

  1. 对于self形参,在类中的任何方法中都必须要有,而且必须放在第一个(如上面的的3个方法中,均有self,且都在第一个);对于__init__()中其他形参,是自己选择填入的,在创建实例时要填入的实参即对应这些形参(见下面的使用类)(注意:不需要给self形参传递实参
  2. 对于其他的方法,则和定义函数是一样的

2.使用类

class Dog():
	def __init__(self, name, age): """初始化属性name和age"""
		self.name = name 
		self.age = age
	def sit(self): """模拟小狗被命令时蹲下"""
		print(self.name.title() + " is now sitting.")
	def roll_over(self): """模拟小狗被命令时打滚"""
		print(self.name.title() + " rolled over!")

my_dog = Dog('doge', 6)
print(my_dog.name)
print(my_dog.age)
my_dog.sit()
my_dog.roll_over()
#输出结果
doge
6
doge is now sitting
doge rolled over
  • 在第10行中用类创建了实例,左边是要创建的实例的名称,右边是类的名称,括号内填入的实参与在定义__ init__()时设定的形参一一对应

  • 如11,12 行,用实例名.属性(my_dog.name)的方式可以获取这个实例的相关属性

  • 如13,14行,用实例名.方法() (my_dog.sit())可以使用这个实例具有的功能

  • 另外实例的属性有很多方法去更改,如直接获取属性更改(my_dog.name=coco),还可以通过方法来更改等等,不再一一列举。

二、类中的相关问题

1.关于创建类中的问题

#下面的例子来自于python编程:从入门到实践
class Dog():
	def __init__(self, name, age): """初始化属性name和age"""
		self.name = name 
		self.age = age
	def sit(self): """模拟小狗被命令时蹲下"""
		print(self.name.title() + " is now sitting.")
	def roll_over(self): """模拟小狗被命令时打滚"""
		print(self.name.title() + " rolled over!")

①. 对于__ init__() :和其他的方法一样,都是由def定义的方法,(因此在其他方法中能执行的如for,print等等都是一样可以在这里面用的),只不过它会在一创建实例时就被调用(如果在def init():下写一个print(‘a’),那么只要一创建实例,就会执行print(‘a’)),因此由它来定义类的属性,因为这样的话,每次创建实例时就要输入init中的参数,就可以在一开始就给实例赋予属性

事实上,也可以在其他方法中创建属性,这样创建的属性和在init中创建的没有区别都是在整个类的所有方法中(而如果仅是方法中的局部变量,则在其他方法中不能使用)都可以使用的
但是,由于其他方法必须在实例创建后调用,因此这些属性必须要调用方法后才能赋予实例,如

def function1(self,attribute):
	self.attribute=attribute
def function2(self):
	print(self.attribute)

因此self.attribute这个属性必须在方法function1被调用后才能被才被赋予实例,而在function2中要用到self.attribute这个属性,所以,要使用function2,必须要先使用function1才行

②.对于selfself是永远指向被创建的实例的,因此在所有的方法中,都必须有self这样形参,而且必须放在第一位参数(事实上,如果不用self,把self改成其他任意名称,如a,把所有的self都换成a也是可以的运行成功的,但是一般都选择self,编译器也会提醒使用self)

def __init__(self, name, age): """初始化属性name和age"""
		self.name = name 
		self.age = age

③.关于属性和形参:(见上)
在类中用self.属性名,来表示属性,因为还未创建实例,不知道实例名是什么,因此用始终指向实例的self指代实例名

上面的例子其中括号内的name是方法__ init__的形参,等号右边的name是括号内的形参name是一样的,等号左边的self.name是class Dog的属性。
在这里形参和属性的名字保持一样,事实上,并不需要保持一样,这样写只是为了更加清晰,如下面的例子,这样写和上面是一样的

def __init__(self, a, b): """初始化属性name和age"""
		self.name = a 
		self.age = b

2.关于类的继承(重点)

一个类继承另一个类时,它将自动获得另一个类的所有属性和方法;原有的类称为父类, 而新类称为子类子类继承了其父类的所有属性和方法,同时还可以定义自己的属性和方法

class Dog():	#父类
	def __init__(self, name, age): """初始化属性name和age"""
		self.name = name 
		self.age = age
	def sit(self): """模拟小狗被命令时蹲下"""
		print(self.name.title() + " is now sitting.")
	def roll_over(self): """模拟小狗被命令时打滚"""
		print(self.name.title() + " rolled over!")

#编写一个Cat的类,并继承Dog
#有如下3种情况
class Cat(Dog):
	pass
  1. 只要在子类的括号内填入父类的名称即可以继承父类的全部,相当于复制了父类的全部代码,但换了一个名字。父类的属性和方法都可以被可以被子类使用,注意,建立实例时,要输入的实参和父类中形参的数目需保持一致,这是最简单的继承
class Cat(Dog):
	def __init__(self,cat_name,cat_age,cat_gender):#重新定义了新属性
		self.cat_name=cat_name
		self.cat_age=cat_age
		self.cat.gender=cat_gender
  1. 如果在子类中用了def __ init__():则父类中的def __ init__():会被覆盖,这就是重写,子类的属性由子类中的def __ init__():重新定义

(如果在父类中有需要用到父类的参数才能运行的方法,同时要在子类中使用这个方法时,如父类中有self.name,并且有个print(self.name),那么因为子类的属性被重写,所以会缺少self.name这个属性,而无法使用这个print,这时的解决办法是在子类中同样再定义一个self.name的属性就可以了)

(因为子类是继承父类的,而除了init被重写了以外,其他都没有变,故只要能提供一个一样名字的参数,就可以继续使用父类的方法了)

class Cat(Dog):
	def __init__(self,cat_name,cat_age,cat_gender):
		super().__init__(cat_name,cat_age)#在重写init的情况下仍想要使用父类的init
		self.cat.gender=cat_gender
  1. 如果在子类中重写了init(即第②种情况),而仍然想要使用父类的属性,那么则要用到super()方法了,super方法在写在子类的def init():下面,从属于def init():
    如上面的③中,def __ init__(self,cat_name,cat_age,cat_gender):中有三个形参(不包括self),其中对于形参cat_name和cat_age我们完全可以直接用父类Dog中的name和age属性,而无需像②中重新写属性,因此通过super()方法来继承,super().后面要继承父类的方法名,这里我们是要继承定义属性的__ init__方法,因此写__ init__()。

理解:这个super后面的__init__是用来与父类联系的,(因此不需要写self形参),括号里面的形参会传递给父类,但其实括号里面的形参名字不需要和父类init括号内的形参的相同,这里的cat_name和cat_age只是起到传递的作用,在创建实例时括号中输入的实参仍是对应def __ init__(self,cat_name,cat_age,cat_gender):里面的实参,super()相当于中转站,把得到的参数传递给父类,调用父类的属性

  1. 另外: 关于super().,这个方法是用来调用父类,如上所见,super().__ init__(),可以用来调用父类的性质,因为__ init__和其他方法没区别,因此,super()同样可以用来调用其他方法,super().function(),和上面调用init是一样的,通常是被用来在重写父类方法后还想调用其方法。 但一般都不需要这样。
def func(): #重写父类方法
	pass
def func_father():
 super().func()    #这样在就可以通过调用func_father来调用父类中原始的func()方法了
  1. “继承”总结: def __ init__()内的形参是Cat这个类定义,可以任意取名字和数量(不必和父类一样),而下面super().__ init__()内形参必须是def __ init__()里面的全部或者部分已定义的形参,它们会像创建一个父类的实例(dog=Dog(a,b))一样把参数传递给父类,调用父类,故名字不必和父类一样,但为了清晰,我们通常是用一样的名字。

总结

本文对类作了简单的介绍,更多具体的方法和细节需要大家自己去阅读书本上的相关详细内容。
本文的重点是对书本上没有详细介绍,初学者容易弄错的问题和细节上作了详细介绍,方便初学者快速理解类。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值