class class_name(super,…): #()以及里在的内容可省略 “”" 类的说明文档 用于 help(class_name)查看 “”" #类的初始化方法 在每一个对象实例化时都会调用 在里面可以增加属性并且赋初始值 #init 方法必须要一个参数self 名字可以不叫self, 它是一个引用 引用正在实例化的对象 #在__init__方法中绑定的属性 在每个实例化的对象中都有 所以如果需要让这个类的所有对象拥有一样的属性 需要在__init__方法给对象绑定 而不是在类外面自行绑定 #为了使每个创建出来的对象拥有不一样的属性值 所以需要__init__接收参数 #__init__方法在实例化对象时调用 class_name() 调用的对应类中的__init__方法 def init(self,x,y): self.x = x #给引用的那个对象绑定一个属性 self.y = y #给引用的那个对象绑定一个属性
#成员方法 需要 对象. 方式才能调用 def member_function(self,…): #必须有一个参数是self(变量名而已 叫啥无所谓) self引用的是调用该方法的对象 xxx.member_function() self 引用的是 xxx 引用的对象
#返回一个字符串 用于在打印 或者 输出对象 自动调用该方法 def __str__(self): return 'class_name'+'...'在类里面 但在方法外面定义 类属性 属于类对对象 可以直接 用 类名.类属性 名的方式进行访问和修改 类的每一个对象 都可以 访问该类属性 但是所有的对象都是共享一份 成员属性是每一个对象拥有独立的一份 如果通过 对象.类属性 = xx 其实是给对象绑定成员属性 如果成员属性和类属性同名 对象.属性 访问到的其实是成员属性
@classmethod #装饰器 def class_method(cls): #类方法 pass 类方法可以直接通过 类名.类方法() 形式进行调用 也可以用 对象.类方法() 形式调用 类方法必须要有一个形参 cls(叫啥名无所谓) 引用类对象 在类方法中可以 cls.类属性 进行访问类属性
@staticmethod def static_method(): #静态方法 pass 所谓的静态方法 相当于只是加了 作用域限制的 全局方法(函数) 调用和类方法的调用一样 类方法的第一个参数 cls 是用于引用 类对象 静态方法所有的参数都必须在调用时传递
python建议不要直接对对象的属性进行直接赋值和访问 不能对赋值数据进行检验合法性
如果用set和get方法话 无疑对调用造成一定的复杂
既保持直接访问的方便 又能对数据进行合法性的检验 起到保护的作用 class class_name(xx): @property def x(self): #在类外看来有一个属性x return self._x @x.setter def x(self,value): self._x = valule #obj.x = value @x.deleter def x(self): del self._x在C++和JAVA中 静态方法和类方法是一个东西 在Python中 静态方法和类方法不是同一个东西
静态语言 VS 动态语言 C、C++、JAVA 都是静态语法 C语言中的结构体 成员属性 事先定义好 事后不能再添加(不能给结构体变量增加新的成员属性)
Python是动态语言 对象定义之后 可以给对象绑定任意的成员属性 除了给对象绑定属性以外 还可以 绑定 方法面向对象的三大特征: 封装 继承 多态
python因为是动态语言 所以可以给对象绑定任意的成员属性 而且也允许对属性进行任意的修改 这种方法很容易对破坏数据的正确性 比如年纪 比较百分制成绩 obj.score = xxx #直接使用这种方式进行绑定和赋值 容易造成数据的无效性 python建议使用方法的形式进行赋值 在使用成员方法对属性进行绑定和赋值时,可以对参数进行检验
对属性进行封装: 私有属性 在类外面不能直接访问 在类外不能直接访问私有属性的原因是因为python对于__的属性进行了改名操作 类名属性名 的方式 在python中,属性名只要以_(双下划线)开头称为私有属性 私有属性的修改和访问 一般来说要提供对象的set和get方法
通过对象.__属性名 = v 这样的形式进行属性绑定 其实是不影响私有属性 因为即使是私有变量 也有方法可以直接访问 私有属性只是一种建议 _ 所以在python中约定以双下划线 或者 单下划线 开始的变量为私有属性 不建议直接访问和赋值在实现类时,把属性和方法设置成私有属性和方法的过程称为封装
python是动态类型语言,对象可以绑定任意的属性 python中也提供了途径来限制 slots 类属性 可以引用一个列表 列表中为允许对象所能够绑定的所有的属性
绑定属性: 对象.属性 = value setattr(对象,属性名,值)
对象有没有为name的属性 name可以是成员属性 也可以是成员方法 hasattr(对象,name)
删除对象的属性 del 对象.属性名 成员方法是不能使用del进行删除的 只读 delattr(对象,属性名)
可以通过getattr来获得对象的某个属性值 getattr(对象,name)
class X: def init(self,…): #初始化方法 在实例化对象时自动调用 用于初台化成员属性 pass def del(self,…): #删除对象的方法 当对象被del或者消亡时自动调用 #用于回收对象的内存 free pass #一般不会写这个方法
python的对象采用的是引用计数的方式 a = X() 创建对象用a引用 该对象的引用计数为1 b = a 该对象的引用计数为2 a和b引用同一个对象 del a 删除的是a变量 该对象的引用计数减1 当一个对象的引用计数变为0时 会去调用__del__
引用计数: 一个对象有多少个变量引用该对象 当对象的引用为0时,该对象的内存可以回收了
C++、JAVA 构造方法 构造函数 创建对象 然后初始化成员属性 python init 只初始化成员变量 python new 创建对象
python2.x class 和 python3.x class python3.x 中所有的class 都是新式类 S和T没有区别 class S: pass class T(object): pass python2.x 中的class有两种 class S: #旧式类 pass class T(object): #新式类 pass
定义类时 可以指定该类继承自什么类 (默认是object) 被继承的类称为父类 或者 超类 当前类称为 子类 或者 派生类 子类拥有父类的属性和方法 继承 (父类中的私有属性和方法也会被继承)
class class_name(super,...)dir(class_name) 方法 obj.dict 获得obj所有属性字典
在实例化子类对象时,如果子类中的__init__没有写 继承父类的,那么实例化子类对象时 实际上调用的方法是父类中的__init__方法 如果子类有实现__init__方法,那么将不会再自动调用父类的中的__init__方法 一般而言,子类的__init__方法中,需要调用父类的__init__方法来绑定父类中的属性 在子类中调用父类的__init__方法 父类名.init(self,…) super().init(…) super(类名,self).init(…)
成员方法调用的本质: obj.member(v1,v2) --> 类名.member(obj,v1,v2)子类继承父类中的方法 如果子类中重新把继承过来的方法重新实现 重写 子类中定义一个和父类中同名的方法
子类对象时调用同名的方法时 调用的是子类自己的方法 多态 (鸭子类型)
C++ JAVA 多态: 父类类型的引用 引用子类对象 父类类型的指针指向子类对象
一个子类可以有多个父类
类名.__mro__ 方法解析顺序 先深度 然后 广度 公共的最后 object 方法解析顺序决定了子类在调用父类中同名方法时调用的是哪一个类中的方法1、在于代码的复用 提高开发效率 2、增加现有类的功能 扩展类的功能
在定义一个类时,可以指定该类继承现有的类(python支持多继承(java中不支持多继承)、多重继承) 被继承的类 称为 父类 or 超类 继承父类的类 称为 子类 or 派生类
子类拥有父类的属性和方法 语法规则: class class_name(base_name,…): #base_name 继承自哪个类 如果不显示指定父类 则默认继承object pass
python3中所有的类都是直接或者间接继承自 object 类isinstance(对象,类) #判断一个对象是否是某个类的实例
判断一个对象的类型: type(对象) == 类型 isinstance(对象,类) 子类对象的类型 和 父类不一样 但是子类对象一定是父类类型的实例
issubclass(类1,类2) 判断类1是否是类2的派生类(子类) issubclass(类1,object) True
定义类 init del self
