类和对象
类的主要组成部分:属性和方法
使用类可以创建出很多对象。只要是这个类创建出的对象都具有相关的属性和方法。但是这些对象又是相对独立的,每次创建出的对象是不同的个体。
#类的定义
class 类名:
属性
方法
定义类时,类名后面可以加括号,可以不加括号,括号里面可以有object,可以没有object,object里面有很多有关类的属性和方法,在python3中会自动继承object的属性和方法。
#创建对象
对象 = 类名()
创建对象时,如果给属性初始化默认值,就需要在括号内加入参数了
#对象调用属性和方法的方式:
对象.属性
对象.方法()
为什么要用__init__函数定义类的属性
先给出代码
class Demo:
#定义属性
def __init__(self,a,b):
self.a = a
self.b = b
#定义方法
def func1(self):
print("类中的方法")
demo1 = Demo(2,4)
print(demo1.a,demo1.b)
demo1.func1()
#output
2 4
类中的方法
使用__init__函数定义类的属性,可以在创建对象时就将属性绑定给对象,并且在__init__函数里面定义的变量在其它方法里面也能使用,这是对象的属性。
__init__函数的工作机制:在类创建对象时会自动调用__init__函数,然后使用__init__函数,将值传给对象,完成属性的初始化。
为什么方法的第一个参数都是self
前面说到每个对象的属性是不同的,而这些属性是能够在方法中去呈现的。当对象实例去调用方法时,实例的属性是有差异的。所以在实例调用方法时,python首先会将该实例传给该方法,而self指的是这个实例,然后在执行函数里面的代码块。
class Demo:
def __init__(self,a,b):
self.a = a
self.b = b
def func1(self):
print("类中的方法")
def func2(self):
print(self)
demo1 = Demo(2,4)
print(demo1)
demo1.func2()
#output
<__main__.Demo object at 0x0000000002E3D278>
<__main__.Demo object at 0x0000000002E3D278>
小结:__init__函数能在创建对象时,完成对象属性的初始化。在调用方法时,会先将对象传入方法中,然后在执行函数内的代码块。
类变量和实例变量
类变量:在类中,在方法以外定义的变量,是公有变量
实例变量:在方法中定义的变量
代码实现
class Demo:
a = 12 #类变量
def __init__(self,b,c):
self.b = b
self.c = c
def func1(self):
print("这是一个比较类变量和实例变量的例子")
#创建两个对象
demo1 = Demo(2,3)
demo2 = Demo(4,5)
#类变量是公有的
print("----------------------不同的对象访问类变量---------------------")
print(demo1.a)
print(demo2.a)
#不同的实例对象有着不同的实例变量
print("-----------------不同的实例对象有着不同的实例变量---------------")
print(demo1.b)
print(demo2.b)
#output
----------------------不同的对象访问类变量---------------------
12
12
-----------------不同的实例对象有着不同的实例变量---------------
2
4
修改类变量的值
demo1.a = 13
print(demo1.a)
#output
13
小结:所有变量调用类变量(属性)的得到的值是一样的,不同对象的调用实例变量(属性)是有差异的。
变量私有化之类的封装
如果想提高代码的安全性,使得变量不能直接被调用,可以在变量前加两个下划线。
class Demo:
gong_you = 20 #类变量
def __init__(self,a,b,c): #实例变量
self.a = a
self.b = b
self.c = c
def func1(self):
print("定义的第一个函数")
demo = Demo(1,2,3)
print(demo.a) #调用类变量
print(demo.gong_you) #调用实例变量
#output
1
20
将变量私有化
class Demo:
gong_you = 20 #类变量
def __init__(self,a,b,c): #实例变量
self.__a = a #变量a私有化
self.b = b
self.c = c
def func1(self):
print("定义的第一个函数")
def getA(self): #创建得到__a的函数
return self.__a
demo = Demo(1,2,3)
print(demo.getA())
print(demo.gong_you) #调用实例变量
#output
1
20
可以看到在变量前面加两个下划线后,说明这个变量你不能直接去调用它了,类似于被保护起来了,可以将它封装在函数中来使用它。对于类变量gong_you也是如此。
类的继承
类是可以继承的,这也是为什么使用类的原因之一。当想要扩展代码时,可以减少代码的重复。
class Human:
a = 12
def __init__(self,age,height):
self.age = age
self.height = height
def learn(self):
print("学习")
class Students(Human):
pass
stu1 = Students(21,178)
stu1.learn()
print(stu1.a)
#output
学习
12
可以看到类Students继承了类Human的属性和方法,比如a,函数__init__(),,learn(),所以创建类Students的对象时,会自动调用类Human里面的__init__函数,需要传入年龄和身高的参数。
需要注意的是,如果在类Students里面重新定义__init__函数,则会将父类的__init__函数覆盖。如果没有会默认使用父类的__init__函数。
抽象类
定义抽象类后,当在类中定义一个抽象方法,子类也必须有这个方法
import abc
class Animals(metaclass=abc.ABCMeta): #定义抽象类
def __init__(self,name,color):
self.name = name
self.color = color
#抽象方法
@abc.abstractmethod
def eat(self):pass #无方法体,子类必须有eat()方法
class Cats(Animals):
def eat(self):
print("吃鱼")
class Dogs(Animals):
def eat(self):
print("吃骨头")
d = dogs("大黄","black")
如果子类,没有eat()方法,则会有TypeError: Can’t instantiate abstract class Dogs with abstract methods eat的错误。需要注意的是抽象类不能创建实例。