命名规则Tips:
(1)变量全部用小写,单词间用下划线连接,如student_age
(2)类名单词首字母大写,单词间不建议用下划线连接,用驼峰式命名,即每个单词首字母大写,如StudentHomework
1.如何构建一个类
(1)类是现实世界或思维世界中的实体在计算机中的反映,它将数据以及这些数据上的操作封装在一起
(2)类最基本的作用:封装变量和函数
(3)类是为了定义和描述类的行为和特征,类的设计是一门艺术,最重要的是找到类的行为和特征,不要在类内部调用定义的函数
(4)一个模块下,不要既定义类,又实例化类,要么全都是实例化,要么全都写类
(5)类就像一个模板,通过类,可以生成很多个对象
class Student():
name = ''
age = 18
def print_info(self):
print('name:' + self.name)
print('age:' + str(self.age))
a.类里的方法()中必须有self
b.方法中变量的引用,前边也必须加self.
不然都会报错
2.类实例化
从另一个模块引用上面定义的类
from t import Student
student = Student()
#与其他语言不同,不需要new
#调用类中的方法:
student.print_info()
返回结果
name:
age:18
3.方法和函数的区别
方法:面向对象层面、设计层面
函数:面向过程层面,是程序运行、过程式的一个称谓
类内部的函数,称作方法比较合适
模块下的函数,称作函数比较合适;
类内部的变量,称作数据成员比较合适
模块下的变量,称作变量比较合适
4.构造函数
(1)认识构造函数
class Student:
def __init__(self):
print('student')
实例化时,构造函数会隐式地自动调用,因此一般不会显式调用构造函数
当显式调用时,构造函数会返回什么值呢?
student1 = Student()
a = student1.__init__()
print(a)
print(type(a))
返回结果
student
student
None
<class 'NoneType'>
从结果可以看出,student打印出了两次,说明第1行实例化时,__init__()函数已经被调用了一次;
第2行显式调用,__init__()函数又被调用了一次;
__init__()返回值为None
那么可以强制__init__()函数返回其他结果吗?我们来试验一下,让__init__()函数强制返回一个字符串:
def __init__(self):
print('student')
return 'student'
运行结果,报错:
student
Traceback (most recent call last):
File "c1.py", line 61, in <module>
student1 = Student()
TypeError: __init__() should return None, not 'str'
错误提示,__init__()函数只能返回None,不能返回其他类型的值
(2)构造函数的作用:以类为模板生成不同的对象
将构造函数改为:
def __init__(self, name, age):
name = name
age = age
if __name__ == "__main__":
student1 = Student()
运行报错:
Traceback (most recent call last):
File "c1.py", line 62, in <module>
student1 = Student()
TypeError: __init__() missing 2 required positional arguments: 'name' and 'age'
构造函数中需要括号内输入name和age两个参数,在实例化时也必须输入
那么入两个值之后,看一下输入的值有没有生效
class Student():
name = ''
age = 0
def __init__(self, name, age):
name = name
age = age
if __name__ == "__main__":
student1 = Student('小明',18)
print(student1.age)
返回结果:
0
说明输入的参数并没有改变类下面定义的变量的值
5.类变量和实例变量
要想理解上面的现象为什么出现,首先需要理解以下两个概念:
类变量:和类相关的变量
实例变量:和对象相关的变量
class Student():
name = ''
age = 0
def __init__(self, name, age):
self.name = name
self.age = age
if __name__ == "__main__":
student1 = Student('小明',18)
print(student1.age)
print(Student.age)
第2/3行中的name和age是类变量
第5/6行中的name和age是实例变量
这是和其他语言很重要的不同之处,要注意!
运行结果:
18
0
运行结果说明,类Student的类变量age和实例student1的实例变量age是不同的,它们两个没有关系
也就是说,第4章中的例子本想打印实例变量,却打印出了类变量
通过__dict__变量(python自带的可以看到类或者对象下所有变量的字典)来看一下
class Student():
name = ''
age = 0
def __init__(self, name, age):
name = name
age = age
if __name__ == "__main__":
student1 = Student('小明',18)
print(student1.__dict__)
返回结果:
{}
说明对象student1下没有任何变量,也就是说print(student1.age)打印了一个不存在的变量,为什么打印的不是none呢?
这就涉及python的一个内部机制,当要打印某个实例变量时,首先在实例变量里找,如果找不到,就会在类变量里找同名的类变量,如果类变量里还是找不到,接下来会在父类里继续找。所以print(student1.age)打印出了类变量age的值
做下修改后
class Student():
name = ''
age = 0
def __init__(self, name, age):
self.name = name
self.age = age
if __name__ == "__main__":
student1 = Student('小明',18)
print(student1.__dict__)
运行结果
{'name': '小明', 'age': 18}
这时对象student1下有了name和age两个变量。
注意:self只和对象有关,实例化了对象1,self就指代1,实例化了2,self就指代对象2,self在实例方法(构造函数是一种特殊的实例方法,和普通的实例方法区别在于1.调用方法不同2.意义不同:构造函数意义在于初始化,普通的实例方法在于操作实例变量)里必须显式出现。
看到上面的例子不禁思考,创建一个类时,直接给类变量赋值有什么意义呢?name和age是描述student这类人的属性的,而这个属性却有具体的值岂不是很奇怪的事情?????
所以说上面对于类变量的用法不合适,通常类变量可以这么用,比如统计基于该类实例化的实例的数量:
class Student():
sum = 0
def __init__(self, name, age):
self.name = name
self.age = age
self.__class__.sum += 1
print('当前班级学生总数为:' + str(self.__class__.sum))
if __name__ == "__main__":
student1 = Student('小明',18)
student2 = Student('小红',17)
student3 = Student('小鱼',19)
student4 = Student('小鹿',20)
student5 = Student('小凯',17)
运行结果
当前班级学生总数为:1
当前班级学生总数为:2
当前班级学生总数为:3
当前班级学生总数为:4
当前班级学生总数为:5
上述类变量累加不仅是可以在构造函数里执行,放在任意一个实例方法里都可以执行
6.变量的作用域(类内的变量和模块内的变量所遵循的规则不同,不要把它们作类比)。也就是说,上面提到的问题,不要用本章的全局变量和局部变量做类比进行记忆
c = 50
def add(x, y):
c = x + y
print(c)
add(1,2)
print(c)
运行结果:
3
50
第一行的c是全局变量
第4行的c是在函数内的局部变量,其虽与第1行的全局变量同名,但通过运行结果可以看出,局部变量的值不能够覆盖全局变量
7.总结
变量用来刻画类的特征
方法用来描述类的行为
实例方法操作实例变量(注意self)
下面看一个例子印证一下:
class Student():
name = ''
age = 0
def __init__(self, name, age):
self.name = name
self.age = age
print(self.name)
print(name)
if __name__ == "__main__":
student1 = Student('小明',18)
运行结果:
小明
小明
第7行的self.name很好理解,打印的是实例变量
第8行的name打印的是哪个变量呢?难道name前不加self.也可以?都代表的是实例变量?
修改一下代码测试一下:
class Student():
name = ''
age = 0
def __init__(self, name1, age):
self.name = name1
self.age = age
print(self.name)
print(name)
if __name__ == "__main__":
student1 = Student('小明',18)
运行结果
小明
Traceback (most recent call last):
File "c1.py", line 64, in <module>
student1 = Student('小明',18)
File "c1.py", line 56, in __init__
print(name)
NameError: name 'name' is not defined
第一个self.name正常打印出来了,但是打印第二个name的时候报错name 'name' is not defined,说明上一个例子print(name)打印的不是实例变量,而是形参name,形参名称一改动,就找不到name这个变量了
因此,在实例方法内部,想访问实例变量,前边一定要加self.
实例方法内部,如何访问类变量呢?
class Student():
gender = ''
name = ''
age = 0
def __init__(self, name1, age):
self.name = name1
self.age = age
print(gender)
if __name__ == "__main__":
student1 = Student('小明',18)
运行结果
Traceback (most recent call last):
File "c1.py", line 65, in <module>
student1 = Student('小明',18)
File "c1.py", line 57, in __init__
print(gender)
NameError: name 'gender' is not defined
报错,说明在实例方法内部,直接访问类变量不可行
方法1:之前说过,在外部,可以直接访问类变量,那么在内部也可以用这种方法
class Student():
gender = 'male'
name = ''
age = 0
def __init__(self, name1, age):
self.name = name1
self.age = age
print(Student.gender)
if __name__ == "__main__":
student1 = Student('小明',18)
print(Student.age)
运行结果
male
0
方法2:利用self.__class__
class Student():
gender = 'male'
name = 'xiaoming'
age = 0
def __init__(self, name1, age):
self.name = name1
self.age = age
print(Student.gender)
print(self.__class__.name)
if __name__ == "__main__":
student1 = Student('小明',18)
print(Student.age)
运行结果
male
xiaoming
0
网友评论