一、类的定义
从逐步的构建类了解面线对象,class构建一个类。比如我们起的一个名字为student,类的命名规则:首字母大写,若有两个单词,两个单词首字母都大写,比如StudentHomework.
在类的内部我们可以定义变量,也可以定义一个函数,并且要是用这样一个类必须要将这个类给实例化:
class Student(): name = "" age = 0 def print_file(): pass student = Student()
在python中直接用类名加上括号完成实例化,那如何调用类的里面的方法,直接用student.print_file(),我们要看到一个结果,可以在方法里面加入一些print:
1 class Student(): 2 name = "" 3 age = 0 4 5 def print_file(): 6 print("name:" + name) 7 print("age" + str(age)) 8 9 student = Student() 10 student.print_file()
但此时,却出现了报错:
PS H:python filesdemo_1> python 1.py Traceback (most recent call last): File "1.py", line 11, in <module> student.print_file() TypeError: print_file() takes 0 positional arguments but 1 was given PS H:python filesdemo_1>
我们所定义print_file这个方法不需要传入任何参数,但是却有一个参数被传入了,我们确实是print_file列表里没有传入任何参数,理论上来讲我们也的确没有传入任何参数。如何解决这个问题呢?Python规定在类下面编写一个一个函数是与在模块里面编写函数是有区别的,我们强制在函数的参数列表里面加入一个固定的关键字self,他就是一个特征。
1 class Student(): 2 name = "" 3 age = 0 4 5 def print_file(self): 6 print("name:" + name) 7 print("age" + str(age)) 8 9 student = Student() 10 student.print_file()
但此时,依旧有报错:
Traceback (most recent call last): File "1.py", line 11, in <module> student.print_file() File "1.py", line 7, in print_file print("name:" + name) NameError: name 'name' is not defined
他说name是没有定义的,但name我们确实是已经定义了,如果把class下面的代码放入模块中,name则称为是全局变量,是没有问题的。这里并不能把name理解成全局变量。要正确的定义name,要是用self关键字:
class Student(): name = "" age = 0 def print_file(self): print("name:" + self.name) print("age:" + str(self.age)) student = Student() student.print_file()
PS H:python filesdemo_1> python 1.py
name:
age:0
此时没有问题!现在就完成了类的定义!
类的最基本作用就是在封装代码!
注意:1、类下面的函数一定要加self
2、要想在函数的内部使用类所定义的变量一定要用self.__
另外:不能再函数print_file里面调用它:因为面向对象是对现实世界的一个刻画,类只负责描述,比如描述一个学生的名称、年龄,定义一个行为,他不会负责去执行代码。运行一个类或调用一个类,必须在类的外部,类的作用是一个封装,若是在类的内部调用,他与模块就没有区别了。非常不推荐在模块里又去定义类,又去完成实例化和方法调用,写类的话在模块里只写类,对类的使用在另外一个模块里。
如何在另一个模块里使用student这个类:from c1 import Student.
2、方法与函数的区别
很多时候我们是在模糊方法与函数的区别,在绝大多数是,在C和C++里成为函数,在Java和c#成为方法。方法是设计层面的一个称谓,函数是程序设计、过程式的一种称谓。面向对象就是一个设计层面的一个东西,对于类,它里面定义的函数应该称谓方法,而如果我们只是把函数定义在模块里应称为函数。
3、类与对象
类和对象的关系是从实例化来关联起来的。类是现实世界或思维世界中的实体在计算机中的反映,他将数据以及这些数据上的操作封装在一起。
对于Student类,除了有名字和年龄是不够的,应该还有他的行为与特征:做家庭作业。那print_file这个行为在Student类下面合适吗?不合适,他可以放在类printer(打印机)下面。我们一定要把握住行为的主体才对,没有找对主体使我们在设计面向对象容易忽视的问题。在这个类下面可以做do_homework这个行为。
如何表示一个具体的学生是对象做的,对象是用来表示一个具体的概念,name、age具体去什么值是实例化的过程,如果没有具体的数据这个就不是一个对象。类就好像是一个印刷机一样,他是一个模板,通过这个模板,我们可以做出各种各样的对象。
4、构造函数
用Student这个模板创造不同的对象:student1=Student()、student2=Student(),利用id()函数,可以看到他们的内存地址是不相同的,但对与我们人来说,他们都是相同的,因为名字年龄一样。但如何通过实例化让他们不想同呢?可以传入不同的参数:那我们可以直接从Student()的括号中写入不同的参数吗?直接这样是不行的!我们需要Student类的内部构造一个特殊的函数!_ _init_ _(self):
1 class Student(): 2 name = "" 3 age = 0 4 # 构造函数 5 def __init__(self): 6 pass 7 8 def print_file(self): 9 print("name:" + self.name) 10 print("age" + str(self.age)) 11 12 13 student = Student() 14 student.print_file()
class Student(): name = "" age = 0 def __init__(self): print("student") # def do_homework(self): # print("homework") student1 = Student() student1.__init__() student student
为什么调用了一次init构造函数却打印了两个student?是因为构造函数的调用是自动进行的,当在实例化时就自动的调用了一次。
(此时有个问题,当我们显示的调用了init的时候,他的返回结果是什么呢?
student1 = Student() a = student1.__init__() print(a) print(type(a)) student student None # 显示的为空 <class 'NoneType'>
)
另外,对于构造函数来讲是不能强制的返回除none以外的类型的值,否则会报错,这是构造函数与普通函数的一个区别:
class Student(): name = "" age = 0 def __init__(self): print("student") return "student" student1 = Student() a = student1.__init__() print(a) print(type(a)) student Traceback (most recent call last): File "C:/Users/Admin/PycharmProjects/spider/1/c1.py", line 14, in <module> student1 = Student() TypeError: __init__() should return None, not 'str'
那么构造函数的作用是:可以让我们的模板生成不同的对象!我们可以在构造函数内部增加参数,例如_ _init_ _(self,name,age):我们就可以在实例化时传入不同的值。
在构造函数内部,我们通常做的事情是初始化这个类的特征值,比如:
class Student(): name = "" age = 0 def __init__(self, name, age): # 构造函数 # 初始化,左边是我们定义的变量,与最上面的name一样,右边的是我们要传入的参数 name = name age = age student1 = Student("浩瀚", 23) print(student1.name)
最后,我们打印的是空字符串,为什么会这样,他打印的是最初我们所命名的“”,这表明我们所实例化的name并没有意义。有可能有人会说,我们定义的是局部变量,局部变量是不可能影响全局变量的,那这么想就错了!我们绝不能认为函数内部的局部变量等同于类里的“局部变量”,他们的机制是不一样的。这里打印的空值的真正原因是什么?我们需要理解两个概念:类变量和实例变量!
(解释:我们想要尝试打印的是一个实例变量而不是类变量,但最终打印了类变量,正确打印类变量应该用print(Student.name),我们可以使用方法__dict__来看一下student1下面究竟有哪些元素,这个方法的主要作用就是打印出这个对象中所有的变量,以字典的形式给出,输入:print(student.__dict__),最终打印出空的字典{},通过加入self之后,打印出{name:浩瀚;age:23})
5、类变量与实例变量
类变量是和类相关联在一起的,实例变量是和对象相关联在一起的。对象是由类这个模板创建出来的。我们当然可以创建student2。对于类下面:name = ""以及age = 0,这个属于类变量,对象是必须要要有一个地方保存它的特征值的,但肯定是不能保存到类变量那里的,如何保存不同对象的特征值?使用self.name 保存name的特征值,self.age保存age的特征值,他们是实例变量:
class Student(): name = "" age = 0 def __init__(self, name, age): # 构造函数 # 初始化,左边是我们定义的变量,与最上面的name一样,右边的是我们要传入的参数 self.name = name self.age = age student1 = Student("浩瀚", 23) print(student1.name)
这个可以正确的运行出名字!另外可以用其他单词如this代替self,但python建议用self.
class Student(): name = "liulu" age = 0 def __init__(self, name, age): # 构造函数 # 初始化,左边是我们定义的变量,与最上面的name一样,右边的是我们要传入的参数 self.name = name self.age = age student1 = Student("浩瀚", 23) student2 = Student("刘璐", 19) print(student1.name) # 打印实例化1的名字 print(student2.name) # 打印实例化2的名字 print(Student.name) # 打印类变量的名字 浩瀚 刘璐 liulu
类变量有什么意义?可以 看一个例子: