类必须在被定义后才能使用,定义一个类也就是定义这一类对象的模板,定义它的属性和方法/Python中提供了class关键字来声明一个类,class中有成员属性和成员方法。Python中类的定义格式如下:
class [类名]:
[语法块]
注意:类名和变量名一样区分大小写。字母相同但是大小写不同的类会被解释器视为两个不同的类。
定义一个类:
class EmptyClass:
pass
在这个例子中我们定义了一个空的类,虽然什么都没有做,但是不影响它的存在。
在使用类之前需要实例化类,类实例化后会成为常见对象。创建对象和创建变量类似,需要先声明对象是哪个类,同时指明变量名称。
class EmptyClass:
pass
empty = EmptyClass()
print(type(empty))
执行结果如下:
<class '__main__.EmptyClass'>
这个例子创建了一个EmptyClass对象,变量名字为“emplt”,同时在内存中为这个对象分配了内存空间。
在创建实例时,很多类可能都需要有特定的初始状态。所以,一个类可以定义一个特殊的方法,叫做构造函数。在Python中,构造函数就是类的__init__方法(init前后都有两个连续的短下划线)。
定义和使用构造函数:
class Dog:
def __init__(self):
print("汪汪汪!")
dog = Dog()
执行结果如下:
汪汪汪!
当一个类定义了__init__方法,类在实例化时会自动调用__init__方法,用于创建新的类实例。在这个例子中,新的实例被创建,同时执行了构造方法,运行了print函数。注意:构造函数的第一个参数是“self”,不能漏掉。
还有一点需要注意的是,构造方法的返回值必须是“None”。在定义构造方法的时候解释器不会报错,但是在实例化的时候Python会输出错误提示“TypeError:init()should return None”。
在构造方法中我们可以初始化一些属性,例如:
class Dog:
def __init__(self,name):
self.name = name
self.age = 3
09
dog = Dog("旺财")
print(dog.name)
print(dog.age)
执行结果如下:
旺财
3
注意:属性(或者叫成员变量、类变量)必须要使用“self”加上点的方式赋值,不能直接定义变量。直接定义的变量的生命周期只会在函数内,函数执行完变量就会被销毁。例如:
class Dog:
def __init__(self,name):
self.name = name
age = 3
dog = Dog("旺财")
print(dog.name)
print(dog.age)
执行这个例子,Python解释器将会提示我们“AttributeError: ‘Dog’ object has no attribute ‘age’”,即“Dog”对象没有“age”这个属性。其实函数__init__的第一个参数 “self” 指的就是实例本身, 在C++等语言中对应的就是“this”指针,可以理解为对实例的属性进行赋值。Python在调用__init__函数的时候会自动的添加实例作为函数的的一个参数。
在类中定义的函数我们称为方法,例如dict字典中的keys方法就是成员方法。自己定义成员方法也很简单,例如:
class Dog:
def __init__(self,name):
self.name = name
def play(self):
print("汪汪汪!我是", self.name)
dog = Dog("旺财")
dog.play()
执行结果如下:
汪汪汪!我是 旺财
从这个例子可以看出,类中的方法和函数定义的方法基本相同。除了方法一定要定义在类里面并且第一个参数必须是“self”(参数名字不强制要求为“self”,但是一般使用名字“self”以与其他参数作区分)外,其他和函数定义的方法没有任何区别。
从前面的例子可以看到,在构造函数中定义了属性,实例可以轻松地获取和修改属性的值。但是有时候我们需要限制实例随意修改属性,这时候就要用私有有属性。定义私有属性很简单,只要在定义属性名字的时候使用两条下划线作为开头,Python解释器就认为这个属性是私有的,外部不能随便访问这个属性。例如:
class Dog:
def __init__(self,name):
self.__name = name
def play(self):
print("汪汪汪!我是", self.__name)
dog = Dog("旺财")
dog.play()
#错误
print(dog.__name)
执行这段代码,Python解释器会输出一段错误提示“AttributeError: ‘Dog’ object has no attribute ‘__name’”。虽然我们在构造方法中给“__name”赋值了,但是在实例中并不能直接访问到“__name”这个一两条下划线开头的成员变量。在平时的实际项目中,我们可以使用这个特性保护一些不想让用户随便修改的属性。例如:
class Dog:
def __init__(self,name):
self.__name = name
self.__age = None
print(self.__name,"生成成功")
def set_age(self, age):
if not isinstance(age,int):
print("输出的年龄必须是数字!")
return False
if age <=0 :
print("年龄必须大于0!")
return False
self.__age = age
print("汪汪汪!今年", self.__age)
dog = Dog("旺财")
dog.set_age("hello")
dog.set_age(-20)
dog.set_age(3)
dog.play()
执行结果如下:
旺财 生成成功
输出的年龄必须是数字!
年龄必须大于0!
汪汪汪!今年 3
在这个例子中,“__age”是私有属性,实例化后只能通过set_age方法设置年龄。在set_age方法中,我们限制了“age”只能是“int”并且其值要大于“0”,有效地限制了实例化后数据的内容,保证了“__age”是一个有效可用的数据。
私有属性,即只能在类内部被操作的属性。同样地,方法也有私有方法,和私有属性一样,私有方法只能在类内部被调用,实例不能直接调用。
例如:
class Dog:
def __say(self,name):
print(name)
def play(self):
self.__say("汪汪汪")
dog = Dog()
dog.play()
#错误
dog.__say()
执行这段代码可以发现play方法可以正常运行,但是__say方法不能直接被实例“dog”调用,Python解释器会提示错误信息“AttributeError: ‘Dog’ object has no attribute ‘__say’”