命名规则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

从结果可以看出,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

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

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

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

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

更多推荐

python构造方法的作用是什么_Python学习(九)--面向对象、构造函数