美文网首页
Python学习(九)--面向对象、构造函数

Python学习(九)--面向对象、构造函数

作者: 白面葫芦娃92 | 来源:发表于2020-03-20 21:58 被阅读0次
命名规则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

相关文章

  • Python学习(九)--面向对象、构造函数

    命名规则Tips: (1)变量全部用小写,单词间用下划线连接,如student_age (2)类名单词首字母大写,...

  • Python 面向对象之第二回合

    函数版用例 面向对象用例 总结 python构造方法 小案例

  • 01 面向对象

    -------------------【面向对象】------- ----《构造函数》--- 简介:所有的构造函数...

  • RYF javascript笔记3

    4. 面向对象编程 4.1面向对象编程概述 4.1.1简介 4.1.1.1构造函数 js没有“类”,而改用构造函数...

  • 构造函数和原型对象

    javascript使用构造函数和原型对象来进行面向对象编程 构造函数 在 JavaScript 中,构造器其实就...

  • js原型prototype原型链__proto__以及必会的ne

    什么是构造函数 构造函数是典型的面向对象编程语言,js的对象语言体系,是基于构造函数和原型链的构造函数是生成对象实...

  • 什么是构造函数?

    什么是构造函数? 典型的面向对象编程语言(比如 Java 和 Python),都有“类”(class)这个概念。所...

  • 2018-11-23 面向对象4 ES6

    面向对象补充: JavaScript 通过构造函数生成新对象,因此构造函数可以视为对象的模板。实例对象的属性和方法...

  • 3-javascript 构造函数

    js中面向对象编程是基于构造函数(consstructor)和原型链(prototype)的。 构造函数作为对象的...

  • 2018-11-22

    JavaScript的面向对象是基于constructor(构造函数)与prototype(原型链)的。 构造函数...

网友评论

      本文标题:Python学习(九)--面向对象、构造函数

      本文链接:https://www.haomeiwen.com/subject/fiflyhtx.html