类的定义
尝试 写出 有意义的面向对象的代码。
从如何构建一个类开始:
核心:类、对象。
变量名采用小写,单词采用下划线连接。
类名首字母采用大写,单词直接连接,每个单词首字母大写(推荐)
类内部:
1.定义变量
2.定义函数
使用类:
先实例化,然后再调用类的方法。
不可在类内部执行代码,只能定义。这样就破坏了类的封装性。
浅读函数与方法的区别:
从另外一个模块引入类然后调用实例的方法。(操作)
方法和函数没有绝对的区别:
方法是设计层面的称谓
函数是程序运行、过程式的一种概念。
类与对象
类和对象到底是什么,它们之间有什么关系。
类和对象是通过实例化关联起来的。
类是现实世界或思维世界的实体在计算机中的反映,它将数据以及这些数据上的操作封装在一起。(特征与行为)
类是一个抽象的概念,一类事物的组成。对象用来表示一个具体的实例。
构造函数
实例化以及实例化的意义:
用类创建一个对象的过程就是实例化。
def __init__(self):
pass
实例化之后的实例属性初始化。实例化函数为__new__
类属性和实例属性!!!
构造函数实例化时会自动调用,也可以显式调用(实际操作中基本不会这么干)。构造函数必须返回None,否则会报错。
构造函数就是为了类能够生成不同的对象。实质就是添加实例属性。
区别模块变量与类中的变量
模块变量 -> 局部变量不会覆盖全局变量 -> 变量的作用域
类变量 <--> 实例变量
类变量与实例变量
两种变量最好不同名
# 类最基本的作用:封装代码
class StudentHomework(object):
# 类属性、最好不与实例属性相同名字
# name = ""
# age = 0
sum1 = 0
def __init__(self, name, age): # self 可替换为别的 名字
self.name = name
self.age = age
StudentHomework.sum1 += 1
def print_file(self):
print("name: " + self.name)
print("age: " + str(self.age))
类与对象的变量查找顺序
查找实例变量时: 先查找实例变量,然后查找类变量,然后查找父类变量。
可以通过__dict__
查看实例变量的值
self与实例方法
1.实例方法参数列表第一个固定放上self(也可以是别的名字,推荐self)接受传入的对象。
2.调用实例方法不需要传入self,self是类自己传入的。
实例方法:和对象实例相关,实例可以调用
类方法和静态方法
在实例方法中访问实例变量和类变量
- Student.num1 类名加类变量
-
self.__class__.sum1
self 加内置的class所属类属性的类属性
记得经常查看内置的函数和属性,或者查看文档,很多东西很重要
类方法
通过装饰器
@classmethod
类方法第一个传入的参数为当前类 推荐使用cls,使用其他的名字也行。
类方法最好通过类调用?以此来明确逻辑?
web框架的orm框架中,查询要采用类方法。因为查询类的数据,此时没有实例。
静态方法
@staticmethod 没有默认传入的类或者实例属性。
推测和外部方法没区别?只是多了一个命名空间?
对象和类都可以调用该静态方法
类方法和静态方法都不能访问实例变量!!!
静态方法和对象关联很弱,不推荐经常使用。能用静态方法的地方都能用cls代替。
成员可见性:公有和私有
廖雪峰--@property -- 对私有变量实现赋值并检查参数和查看
廖雪峰--私有变量--双下划线python将复杂化访问参数。单下划线约定为私有,虽然可访问
尽量不要直接在对象外部对成员进行赋值,通过方法赋值。
名字前面加上双下划线,python将会将属性或者方法私有化,本质是改变了变量名。
如果前后都加入了双下划线,依旧是共有的。这种命名方式为类的内置变量和方法命名方式。不推荐使用。
没有什么是不能访问的
名字前面加上双下划线,python将会将属性或者方法私有化,本质是改变了变量名。!!!依旧可以通过改变后的变量名进行访问赋值。
继承
面向对象三大特性:继承性、封装性、多态性
类:类的属性和方法
继承:避免定义重复的属性和方法
先学好单继承,再去用多重继承。
init通过super函数传递
def __init__(self, name, age): # self 可替换为别的 名字
super(StudentHomework, self).__init__(name, age)
# 以上等价于 Human.__init__(self, name, age)
# 以下两种操作等价。第二种更好,个人感觉,使实例方法看上去更加独立
StudentHomework.sum1 += 1
self.__class__.sum1 += 1
self.__score = age # 外部访问变量名编程_classname__score
student1.print_file() 等价于 Student.print_file(student1)
继承的init传递,需要传递参数self。因为用父类调用自己的__init__
,就是普通的方法调用,如果不传入子类的实例,就会导致参数缺失。
-> Human.__init__(self, name, age)
super关键字
开闭原则:对拓展开放、对更改封闭。
采用super
-> 子类方法与父类方法同名,采用super将父类的方法加入到子类中
多继承、多态性暂时没讲。。。 通过class.mro 查看继承顺序