面向对象编程

面向对象编程的优点:高复用,易维护,易扩展,开发效率高

类和函数的区别

  • 函数只是提供操作数据的过程和算法,自身并不能保存数据

  • 类不但提供了操作数据的过程和算法,它还可以保存相关的数据

概念:

类:类是一个模板,他描述这一类对象的行为和状态,类的命名使用驼峰式记法(以大写字母开头,并且后面跟的任意一个单词都是以大写字母开头)

对象:有着相应行为的数据集合,对象就是类的实例

面向对象:面向的意思理解为指向,综合起来就是功能上指向有着相应行为的数据集合

实例:是通过这个模板生产出来的产品(添加不同的初始化值)

实例化:创建类对象的一个过程,一般是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' # 有则改,无则增, 不会去改变实例属性的值    

 

方法:就是行为,看上去像函数

实例方法:定义参数一定要有self,只能实例调用, 可以使用实例变量和类变量

类方法:方法上面要有@classmethod 必须有一个cls的方法参数,传类对象的内存地址的 里面不能使用self.xxx的实例变量,可以通过类名或者实例名进行调用。

静态方法:方法上面要有@staticmethod 可以没有任何参数,里面不能使用self.xxx的实例变量,可以通过类名或者实例名进行调用。

类对象存储:类对象会存储类变量和所以类中定义的方法(实例方法, 静态方法,类方法)

实例对象存储:实例变量的内容,和类对象的地址

备注:不管是实例方法、类方法或者静态方法,都是存在类对象的内存地址的,全局只有一份

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() 

 

私有方法:双下划线开头的方法

备注:

  • 私有方法:私有方法的名字前面需要有2个_

  • 只能在类内部的其他方法中调用私有方法

  • 在类的外部不允许直接调用私有方法

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())
   ('南北', '吴老师')
   
   # 多继承:从左往右继承,当名称相同时,优先使用左边继承的那个方法
   

 

posted @ 2020-03-17 10:17  海澜时见鲸  阅读(187)  评论(0)    收藏  举报