• python -- 面向对象


    Python从设计之初就已经是一门面向对象的语言,正因为如此,在Python中创建一个类和对象是很容易的。

    在python中,一切皆对象。在学习python的面向对象程序设计之前,先来看看面向对象的基本特征。

    面向对象技术简介

    • 类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
    • 类变量:类变量属于类本身,不属于任何一个实例。实例可以访问其对应类的类变量,但不能修改。
    • 成员变量:成员变量定义在类的构造方法里面,在实例化对象是生成,属于某个特定对象,不属于类。
    • 方法重载:子类从父类继承的方法不满足子类的需要时,可以先重载,再继承,这样来进行扩展或修改。
    • 继承:子类继承自父类,这样子类就能拥有从父类继承过来的东西。通常用子类来对父类进行扩展。(父类更多的是公同拥有的,子类就是进行个性化)
    • 实例化:创建一个类的实例,类的具体对象。
    • 方法:类中定义的函数。
    • 对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。

    面向对象思想

      1、面向对象特点:封装、继承、多态
      2、面向对象程序设计思想:
        先整体构想,规划多个对象,再由对象特性分别设计类
        由类实例化不同的对象
        由多个对象组合完成整个程序
      3、python中的子类可以继承多个父类(一般就1-2个,python3新式类、经典类继承都是广度优先,python2中新式类采用广度优先,经典类采用深度优先)
      4、封装,继承都是为了代码重用
      5、多态:(一个接口,多重实现)接口重用 (注:python自身不支持多态,但可以用代码实现类似效果)

    Python中的面向对象

    一、类的详解

      

     1 例如:
     2 class Role(object):
     3     ac = None    #类的变量,随着类的创建,存在与内存中
     4     
     5     def __init__(self,name,role,weapon,life_value):
     6         self.name = name
     7         self.role = role     #这都是成员变量(实例化的对象的变量)
     8         self.weapon = weapon
     9         self.life_value = life_value
    10         
    11     def buy_weapon(self,weapon):
    12         print('%s is buying [%s]' %(self.name,weapon))
    13         self.weapon = weapon
    14 
    15 在这个类里面,有一个类的变量ac,可以理解为静态变量,要修改ac的值,需要通过' Role.ac = xxx ',即 类名.类变量名
    16 
    17 类变量与成员变量区别:
    18      1、类变量在定义类时就存在于内存中了,而成员变量只有在实例化时才被构造方法创造
    19      2、定义时,成员变量前面都有self,而类变量没有。因为self时指向的不同对象,而类变量只
    20         能由‘类名.类变量’来修改,可以通过‘对象.类变量’来访问,但是不能修改
    21 
    22 类不能直接调用实例变量(实例变量存储在对象中,不在类中)
    23      
    24 __init__() 是构造方法,在实例化对象时自动调用,就是用来初始化对象属性等
    25 
    26 在实例化对象时,根据构造参数传递参数
    27 
    28 定义类时,里面属性前面都有一个self,方法的第一个参数默认是self,这个self是指向实例化的对象,不是指向的类
    29     
    30 
    31 内存详解:
    32     在类定义时,就在系统内存里面生成了一块内存来存放类的内容,包括 类变量、类方法 等
    33     即:类变量存储在类里面,类里面的方法也是存储在类这块内存里面的
    34     
    35     构造函数是在实例化对象才会调用,所以构造函数里面的属性都是存在于实例化的对象的内存里面(是特定对象的属性)
    36 
    37 对象调用类的方法:
    38     在实例化对象时,并没有把类里面的方法都copy到对象内存空间里面,所以对象的内存空间里面只有属性,并没有方法
    39   方法都是存在于类的内存中(这样就算是实例化了无数个对象,方法在内存中还是只有类空间里面这一份,节约空间)
    40   方法都是类的方法,实例化对象在调用方法时,都会去类空间里面找。

      类里面有共有属性和私有属性

     1 '''
     2  私有属性:只能在类里面通过类自己的方法调用,对象不能直接调用(可以通过方法)
     3  要把一个属性变为私有属性,只需要在属性名前面加两个下划线'__'
     4  
     5  (特例,尽量别用)从外部直接访问私有变量方法: t._Human__life
     6 
     7 '''
     8 
     9 class Human(object):
    10     __num = 10
    11     def __init__(self,name):
    12         self.name = name
    13         self.__life = 100
    14         
    15     def interface1(self):
    16         print('血量 self.__life:',self.__life)
    17     
    18     def interface2(self):
    19         print('__num:',self.__num)
    20         
    21         
    22 t = Human('Tom')
    23 print(t.name)
    24 #print(t.__life)
    25 '''
    26 builtins.AttributeError: 'Human' object has no attribute '__life'
    27 因为__life 是对象里面的私有属性,在外部不能直接调用,但可以通过方法调用
    28 '''
    29 t.interface1()  #血量: 100
    30 #print(Human.__num)
    31 '''
    32 builtins.AttributeError: type object 'Human' has no attribute '__num'
    33 '''
    34 t.interface2()
    35 
    36 print("特例访问私有变量方法 t._Human__life :",t._Human__life) 

      类里面不常用的特殊方法

     1 #!/usr/bin/env python
     2 #coding:utf-8
     3 
     4 class A(object):
     5     '''Test class'''
     6     num = 10
     7     
     8     #类里面的__init__()是由__new__()触发执行的
     9     #def __new__(self):
    10         #print("=======new======")
    11     '''
    12     =======new======
    13     None
    14     报错:builtins.AttributeError: 'NoneType' object has no attribute '__module__'
    15     说明在这里重载__new__()方法后,没有再执行__init__()
    16     '''
    17     def __init__(self,name,age):
    18         self.name = name
    19         self.age = age
    20         print('__init__')
    21     
    22     def __call__(self):
    23         print("__call__")
    24     
    25     def test(self):
    26         print("=====test=====")
    27     #重载析构函数
    28     def __del__(self):
    29         print('deleting the ...')
    30 
    31 a = A('root',20)
    32 print(a.__doc__)   
    33 '''
    34 Test class
    35 __doc__ 获取类的说明(即:注释)
    36 在定义类的函数时,最好在注释里面对其作用、功能、参数等做个说明
    37 '''
    38 '''
    39 __module__ 表示当前操作的对象或类在那个模块
    40 
    41 __class__     表示当前操作的对象的类是什么
    42 '''
    43 print(a.__module__)
    44 '''
    45 __main__ 在这里代表的是当前模块。如果对象a在其他模块,则会打印a所在的模块名
    46 '''
    47 #import test.Human
    48 from test import Human
    49 #from test import h
    50 h1 = Human()
    51 #print(h.__module__)   #test
    52 print(h1.__module__)   #test
    53 print(h1.__class__)   #<class 'test.Human'>
    54 
    55 #python中,析构函数是: __del__()   析构函数会自己在程序执行结束自动调用
    56 
    57 '''
    58  __call__  对象后面加括号,触发执行。
    59 注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;
    60 而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()
    61 '''
    62 #执行__call__ 方法
    63 a()  #__call__
    64 #A()()   #__call__
    65 
    66 '''
    67  __dict__    只能显示对象中的所有成员变量,不能显示类变量
    68 
    69 我们知道:实例变量(成员变量)属于对象;类中的静态变量和方法等属于类,
    70 '''
    71 print(a.__dict__)
    72 '''
    73 {'name': 'root', 'age': 20}
    74 '''
    75 print(type(a))   #<class '__main__.A'>
    76 print(a)  #<__main__.A object at 0x000001BA3967D128>
    77 
    78 #类是由'type'创造出来的
    79 print(type(A))    #<class 'type'>

      类的方法

     1 #!/usr/bin/env python
     2 #coding:utf-8
     3 
     4 '''
     5 @classmethod  类方法装饰器(不能访问实例变量)
     6   作用:把装饰的方法变为类方法(相似于类变量,只能通过类来访问,对象不能访问类方法)
     7 
     8 @staticmethod  静态方法装饰器(不能访问类变量和实例变量)
     9   作用:类的工具箱,与类直接相互独立,要调用类的东西只有传参(一般不用)
    10   
    11 @property 类属性装饰器
    12   作用:把装饰的方法变为一个属性(能调用,不可执行)
    13 
    14 '''
    15 class Animal(object):
    16     hobbie = "meat"
    17     def __init__(self,name):
    18         self.name = name
    19         self.num = None
    20      
    21     @classmethod    #类方法,不能访问实例变量
    22     def talk(self):
    23         print('%s is talking...' %self.hobbie)    #可以直接调用,但不能修改
    24         #print('%s is talking...' %self.name)
    25     '''
    26     builtins.AttributeError: type object 'Animal' has no 
    27     attribute 'name'
    28     '''
    29      
    30     @staticmethod
    31     def walk(self):
    32         print('%s is walking...' %self.name)
    33     '''
    34     builtins.TypeError: walk() missing 1 required positional 
    35     argument: 'self'
    36     不知道self是谁,在调用时应该把self当参数传进来
    37     '''   
    38        
    39     @property
    40     def habit(self):
    41         print("%s habit is xxoo" %self.name)
    42     '''
    43     builtins.TypeError: 'NoneType' object is not callable
    44     ''' 
    45     
    46     #property 用法补充
    47     #1、直接调用(此时不能传值,否则报错)
    48     @property
    49     def total_player(self):
    50         print("this is a property")
    51         return self.num
    52     
    53     #2、经过1后,total_player变成了属性,因此可以用setter
    54     @total_player.setter
    55     def total_player(self,num):
    56         self.num = num
    57         print("self.num:",self.num)
    58         
    59     #3、相对于2可以给属性传值,那么也可以用删除属性值
    60     @total_player.deleter
    61     def total_player(self):
    62         print("total player got deleted")
    63         del self.num
    64     
    65 d = Animal('zhaolin')
    66 d.talk()
    67 d.walk(d)
    68 d.habit
    69 #1:
    70 d.total_player
    71 #2:
    72 d.total_player = 20
    73 #3:
    74 del d.total_player    #用deleter时,要这样调用
    75 
    76 '''
    77 meat is talking...
    78 zhaolin is walking...
    79 zhaolin habit is xxoo
    80 
    81 this is a property
    82 self.num: 20
    83 total player got deleted
    84 
    85 '''

       

    二、类的使用

      继承:由一般(很多类都具有的共性)到特殊(不同的类有不同的特性)

      子类继承父类时,构造方法需要 【先重写,再继承】
     1 #!/usr/bin/env python
     2 #coding:utf-8
     3 
     4 '''
     5 继承:由一般(很多类都具有的共性)到特殊(不同的类有不同的特性)
     6 
     7 子类继承父类时,构造方法需要 【先重写,再继承】
     8 '''
     9 
    10 class SchoolMember(object):
    11     def __init__(self,name,age,sex):
    12         self.name = name
    13         self.age = age
    14         self.sex = sex
    15         self.enroll()
    16         
    17     def enroll(self):
    18         print('[%s] was enrolled!' %self.name)
    19         
    20     def tell(self):
    21         print('[%s] is telling!' %self.name)
    22         
    23 class Teacher(SchoolMember):
    24     def __init__(self, name, age, sex,course,salary):   #先重写
    25         super(Teacher,self).__init__(name,age,sex)    #再继承
    26         self.course = course
    27         self.salary = salary
    28     
    29     def teaching(self):
    30         print('Teacher [%s] is teaching [%s]' %(self.name,self.course))
    31         
    32     def get_salary(self):
    33         print('Teacher [%s] is saving salary [%s]' %(self.name,self.salary))
    34         
    35 class Student(SchoolMember):
    36     student_nums = 0
    37     def __init__(self, name, age, sex,course,tuition):   #先重写
    38         super(Student,self).__init__(name,age,sex)     #再继承
    39         self.course = course
    40         self.tuition = tuition
    41         Student.student_nums += 1
    42     
    43     def enroll(self):            
    44         #super(Student,self).enroll()   #在子类里面重写enroll(),不继承    
    45         print('The [%s] student [%s] is enrolled!' %(self.student_nums,self.name))
    46         #这里可以用self.student_nums,是因为只是访问student_nums,而没有修改它
    47         
    48     def studying(self):
    49         print('Student [%s] is studying!' %self.name)
    50     
    51     def pay_tuition(self):
    52         print('The tuition of Student [%s] is [%s]' %(self.name,self.tuition))
    53  
    54 #实例化对象        
    55 t1 = Teacher('txowner', 22, 'male', 'python', 3000)
    56 t2 = Teacher('xtsec', 24, 'male', 'php', 2500)
    57 '''
    58 实例化对象的过程:
    59     eg:t2 = Teacher('xtsec', 24, 'male', 'php', 2500)
    60         1、t2 = Teacher() 在内存中开辟一块内存,让t2指向该内存
    61         2、Teacher(t2)  把t2这块内存与类Teacher相关联(这也是为什么self是指向对象的而不是类)
    62         3、把各个参数传递给类的构造方法,在对象t2空间里面创建各个成员变量
    63         
    64 '''
    65 
    66 s1 = Student('root', 20, 'male', 'python', 15000)
    67 s2 = Student('lucy', 18, 'female', 'php', 12000)
    68 
    69 t1.teaching()
    70 t2.teaching()
    71 s1.studying()
    72 s2.studying()
    73 print('t1老师的salary:',t1.salary)
    74 print('s2同学的tuition:',s2.tuition)
    继承
     1 #!/usr/bin/env python
     2 #coding:utf-8
     3 
     4 '''先实验老式类(经典类)的写法'''
     5 
     6 #class A(object):   #新式类
     7 class A:   #经典类
     8     def f2(self):
     9         print('f2 from A')
    10 
    11 class B(A):
    12     def f1(self):
    13         print('f1 from B')
    14         
    15     def f2(self):
    16         print('f2 from B')
    17         
    18 class C(A):
    19     def f2(self):
    20         print('f2 from C')
    21         
    22 class D(B,C):
    23     pass
    24 
    25 d = D()
    26 d.f1()
    27 d.f2()
    28 '''
    29 f1 from B
    30 f2 from B
    31 
    32 由以上结果可知:在多继承时,若多个父类都有相同方法或属性,则按照广度优先方式继承
    33 即:继承父类的方法时,若都有相同方法名的方法,则按照继承时的顺序从左至右继承一个
    34 '''
    35 '''
    36 在python2.x版本:
    37 
    38     深度优先:同一条线上优先,比如上面如果按照深度优先的话,D在调用f2时,先去找
    39 父类B,如果B里
    40 面没有f2,那么D就会去调用A里面的f2,而不会调用C里面的f2,老式类就是这样
    41 
    42     广度优先:同一水平层次优先,比如上面如果按照广度优先的话,D在调用f2时,先去找
    43 父类B,如果B里面没有f2,那么D就会去调用C里面的f2,而不会调用A里面的f2,新式类就是
    44 这样
    45 
    46 在python3.x版本:
    47     不管是新式类还是经典类,在继承时,都采用广度优先
    48 '''
    多继承

      python实现多态调用

     1 #!/usr/bin/env python
     2 #coding:utf-8
     3 
     4 '''
     5 python没有多态。多态是java、c#、c++这类强类型语言特有的
     6 
     7 python可以利用函数等方式来实现多态现象。
     8 
     9 '''
    10 class Animal(object):
    11     def __init__(self):
    12         print('Animal Class')
    13     
    14     def talk(self):
    15         pass
    16 
    17 class Dog(Animal):
    18     def __init__(self):
    19         print('Dog Class')
    20         
    21     def talk(self):
    22         return ('woof!woof!') 
    23         
    24 class Cat(Animal):
    25     def __init__(self):
    26         print('Cat Class')    
    27     
    28     def talk(self):
    29         return ('muaao~')
    30         
    31 dog = Dog()
    32 cat = Cat()
    33 dog.talk()
    34 cat.talk()
    35 
    36 #利用函数实现统一接口
    37 def animal_talk(obj):
    38     print(obj.talk())
    39     
    40 animal_talk(dog)
    41 print('=====')
    42 animal_talk(cat)
    多态调用

    三、反射的妙用

     1 #!/usr/bin/env python
     2 #coding:utf-8
     3 
     4 '''
     5 反射是非常非常重要的!
     6 反射的作用:通过一个字符串来去调用一个对象中名字跟字符串值相同的方法(属性)的内存地址
     7 '''
     8 
     9 import sys
    10 
    11 class WebServer(object):
    12     def __init__(self,host,port):
    13         self.host = host
    14         self.port = port
    15         
    16     def start(self):
    17         print("Server is starting...")
    18     def stop(self):
    19         print("Server is stoped...")
    20     def restart(self):
    21         self.stop()
    22         self.start()
    23         
    24 def test_run(ins,name):
    25     print("test_run",name,ins.host)
    26     
    27         
    28 if __name__ == '__main__':
    29     #print(sys.argv[0],sys.argv[1])
    30     '''
    31     sys.argv是一个获取文件名后面参数的数组,sys.argv[0]是当前文件路径,
    32     后面依次为传递的参数
    33     '''
    34     server = WebServer('localhost', 8080)
    35     if hasattr(server, sys.argv[1]): 
    36     #if hasattr(WebServer, sys.argv[1]):   #对象或类名都可以   
    37         func = getattr(server,sys.argv[1])   #得到对象server中名字与传入字符串相等的函数(方法)
    38         func()
    39     else:
    40         print("your input incorrect!")    
    41      
    42     #server1 = WebServer('localhost1', 80)
    43     #setattr(server1,'run',test_run)
    44     #server1.run(server1,'admin')
    45     
    46     #delattr(server1,'port')
    47     #print(server1.port)   
    48     #AttributeError: 'WebServer' object has no attribute 'port'
    49     
    50     '''
    51     以下的obj可以是类,也可以是实例化的对象
    52     
    53     hasattr(obj,attr)  判断对象中有没有指定属性(方法)
    54     
    55     getattr(obj,attr)  获取对象中的属性(方法)的内存地址
    56     
    57     setattr(obj,attr,method)  把方法(属性)method添加到对象中,并改名为attr
    58         通过对象调用method:obj.attr
    59        
    60         这样把方法(属性)添加到对象中与原生方法区别:
    61           不会自动把self传进去,若要调用obj原生属性,只有先把obj当成参数传进去
    62     
    63     delattr(obj,attr)  把对象obj里面的attr属性(方法)删除掉
    64          注意:因为实例化对象的方法是存在于类中,对象只是能访问类中的方法,不能
    65            更改,但是对象可以更改自己的成员变量。所以这里的attr是对象自身的属性
    66            或方法,不是类里面的。
    67          
    68          可以通过delattr(classname,attr)来删除类的属性(方法)
    69     
    70     '''
    71     '''
    72     #方式比较low
    73     cmd_dict = {
    74         'start':server.start,
    75         'stop':server.stop,
    76         'restart':server.restart
    77     }
    78     if sys.argv[1] in cmd_dict:
    79         cmd_dict[sys.argv[1]]()
    80     else:
    81         print("your input incorrect!")
    82    
    83     '''
    84     
  • 相关阅读:
    echarts基础使用
    将数据表中的热词统计结果用echarts热词云展示
    LInux下bash: wget: command not found解决方法
    利用Jieba对txt进行分词操作并保存在数据库中
    idea运行Guns示例demo
    浅谈一下mshta在CVE201711882里的命令构造
    CVE201711882 POC 全版本通杀
    本地复现Flash 0day漏洞(CVE20184878)
    Oracle安装错误
    oracle远程连接服务器出现 ORA12170 TNS:连接超时 解决办法
  • 原文地址:https://www.cnblogs.com/xtsec/p/6963638.html
Copyright © 2020-2023  润新知