面向对象编程
面向对象编程的优点:高复用,易维护,易扩展,开发效率高
-
函数只是提供操作数据的过程和算法,自身并不能保存数据
-
概念:
类:类是一个模板,他描述这一类对象的行为和状态,类的命名使用驼峰式记法(以大写字母开头,并且后面跟的任意一个单词都是以大写字母开头)
对象:有着相应行为的数据集合,对象就是类的实例
面向对象:面向的意思理解为指向,综合起来就是功能上指向有着相应行为的数据集合
实例:是通过这个模板生产出来的产品(添加不同的初始化值)
实例化:创建类对象的一个过程,一般是classname()
class P():pass # 类的定义 p = P() # 实例化,参数由__init__决定 p1 = P() p2 = P() # 实例对象可有多个 #备注:类定义的所有内容在内存中只有一份(类属性和类方法),而通过实例化生成的实例对象(多个)都是拥有各自的独立内存空间,实例之间互不影响。
类属性:在类中且在函数外的变量,
实例属性:init初始化生产的和实例方法单独传的叫实例变量
class A(): bar = "aa" # 类属性,全局变量,都可以使用 def __init__(self, name): # 公共的实例属性 self.name = name def func1(self, age): # 独有的实例属性 return self.name, A.bar # 类属性的调用 A.bar # 这个是类外面和类里面都可以这样调用 cls.bar # 通过classmethod装饰器才能这样调用,这是在类里面 # 实例属性的调用 p1 = A('nanbei') p1.name
类私有属性:双下划线开头的类属性就是类私有属性,不允许外部直接访问(classname.属性名或 实例.属性名)
实例私有属性:双下划线开头的实例属性就是私有属性,不允许外部直接访问
备注:
-
在类的外面禁止访问,例如:实例名.私有变量名 是无法读到值的。
-
如果要访问私有属性,只能定义方法进行传递
-
class Person(): __ele = 'out of params' def __init__(self, name, age): self.__name = name self.__age = age def get_date(self): return self.__age if __name__ == '__main__': p1 = Person('南北', '18') print(p1.get_date()) print(Person.__age) print(p1.__name) -------------------------------------- 18 Traceback (most recent call last): File "D:/svn_auto3/test.py", line 486, in <module> print(Person.__ele) AttributeError: type object 'Person' has no attribute '__ele'
属性的作用范围
class Attr(): out_attr = "out_attr" out_other = "out_other" def __init__(self): inner_attr = "inner_attr" # 这个属性是该函数的私有变量,不管是类还是实例都是不能调用的 self.inner_attr = "self.inner_attr" self.out_attr = "self.out_attr" >>>out = Attr() >>>out.out_attr # 当类属性和实例属性都有这个时,优先调用实例属性 self.inner_attr >>>out.out_other # 当类属性存在而实例属性没有时,那么这个实例也会去调用类属性 out_other >>>Attr.out_attr # 调用类属性时只从类属性里面去查询,而不会去实例属性里面去查找 out_attr >>>Attr.inner_attr # 不能去调用实例属性 Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: type object 'Attr' has no attribute 'inner_attr' >>>out.inner_attr # 它会优先调用实例属性,带有self属性的 self.inner_attr # 修改 >>>out.out_attr = 'self.out_attr22' # 有则改,无则增,不会去改变类属性的值 >>>Attr.bar = 'aaa' # 有则改,无则增, 不会去改变实例属性的值
方法:就是行为,看上去像函数
实例方法:
类方法:
静态方法:
class Person(): def func1(self): # 实例方法,self代表的是实例本身,用来找到实例对应的内存位置,即找到初始化的参数 pass @property def func2(self): # 实例方法,使用这个装饰器不能传入独立的实例变量 pass def func3(): # 类方法 pass @classmethod def func4(cls): # 类方法(常用的定义方法) pass #实例方法调用 p = Person() # 首先要实例化才能调用类方法 p.func1() p.func2 # 装饰器的作用:像调用属性一样调用方法 #类方法调用,无需实例化 Person.func3() Person.func4()
-
-
只能在类内部的其他方法中调用私有方法
-
class Person: # 类定义,类对象:类变量和方法 __COUNT = 0 # 类变量 def __init__(self,name,age):# 构造函数 self.name = name # name是局部变量,存到实例变量里面 self.__age = age # 私有变量 Person.__COUNT+=1 # 对类变量进行累计 print(self.name,self.__age) # 这句话会被调用2次 def get_age(self): print(Person.__COUNT) return self.__age def set_age(self,age): #设定了年龄的修改规则 if isinstance(age,(int,float)) and (age>0 and age<200): self.__age = age def __count_person(self):#私有方法 return Person.__COUNT #返回了一个类变量 def get_count(self):#在实例方法中调用私有方法 return self.__count_person() p1 = Person("吴老师",18) #实例化的时候,自动调用__init__方法 #吴老师自动传给__init__里面的name变量 p2 = Person("李老师",28) print(p1.get_count()) class Person: #类定义,类对象:类变量和方法 __COUNT = 0 #类变量 def __init__(self,name,age):#构造函数 self.name = name #name是局部变量,存到实例变量里面 self.__age = age #私有变量 Person.__COUNT+=1 #对类变量进行累计 def __str__(self):#当你打印一个实例的时候,会自动调用 return "%s是个好人!" %self.name def __repr__(self):#交互模式下,不用print,直接写实例变量名称 #则自动调用此方法 return "%s是个坏人!" %self.name # #没有定义__str__方法,但是定义了__repr__方法,则print(实例名),会自动调用__repr__方法 def __iter__(self):#把实例编程一个可迭代的对象 return iter([1,2,3,4]) p1 = Person("吴老师",18) #实例化的时候,自动调用__init__方法 #吴老师自动传给__init__里面的name变量 p2 = Person("李老师",28) print(p1) print(p2) p1 # 交互模式下,不用print(),这时调用的时 __repr__ p2 for i in p1: # 把实例赋予可迭代的能力 print(i)
继承:即一个派生类(derived class)继承基类(base class)的字段和方法。
# 继承方法有两种 class Person(): def __init__(self, name, age): self.name = name self.age = age pass class A(Person): def __init__(self, name, age, mertor): # 重写:当需要增加参数的时候就需要重写,名字必须相同 self.mertor = mertor super().__init__(name, age) # 方法一:使用super来进行继承,不需要传self # super(A, self).__init__(name, age) 方法二:注意super括号里面写的内容 # Person.__init__(self, name, age) 方法三:通过实例化来继承,必须传self def get_info(self): return self.name, self.mertor a = A('南北', 18, '吴老师') print(a.get_info()) ('南北', '吴老师') # 多继承:从左往右继承,当名称相同时,优先使用左边继承的那个方法