zoukankan      html  css  js  c++  java
  • Python 面向对象基础(类、实例、方法、属性封装)

    python是面向对象语言,一切皆对象。


    面向过程:

    变量和函数。 “散落” 在文件的各个位置,甚至是不同文件中。看不出变量与函数的相关性,非常不利于维护,设计模式不清晰。

    经常导致程序员,忘记某个变量的相关性,而导致无法检测的错误。

    面向对象:

    相关的变量和函数都“封装” 在对象里,以对象为单位来管理代码。变量与函数的相关性清晰,利于维护,设计模式清晰。

    程序员可以配合“继承” 来提高代码的可重用性,加强合作开发。

    类与实例之间的关系:

    例如:小明是个人类,小明是真实存在的,而人这个属性是个抽象的类。所以小明是人类里面的具体的实例。

    类:是一类事物的抽象,不是真是存在的。描绘了该类事物的共性,例如:“人”、“动物”、“家具”。

    实例:某类事物的具体个体,是该类事物的具体表现,它是真实存在的。例如:“小明”是具体的某个“人”,  “加菲猫”是具体的某个“动物”。


    创建类:

    class Person:      #使用class关键字定义一个类,这里定义一个Person类。
    	pass       #使用pass占位,保证不会出现语法错误。 

    创建实例:

    >>> class Person:     
    	pass          
    
    >>> p1 = Person()       #类似于函数调用,返回一个具体的实例(实例化一个具体的人)
    >>> p2 = Person()       #在实例化一个人
    >>> print(p1 is p2)     #比较两个人是不是同一个。明显不是同一个。
    False 
    >>> 
    

     


    isinstance 判别函数

    想象一下,当你不确定一个变量是什么类的实例时,如何确定你的猜测呢?

    方法:isinstance(obj, class_or_tuple, /)    #同时比较多个类,如:isinstance(d1,(Person,Dog))

    详细用法: help(isinstance)

    >>> class Person:   #定义一个Person类
    	pass
    
    >>> class Dog:      #定义一个Dog类
    	pass
    
    >>> p1 = Person()   #实例化一个人类p1
    >>> d1 = Dog()      #实例化一个狗类d1
    >>> print(isinstance(p1,Person))  #使用isinstance判断p1这个实例是不是Person实例化来的
    True
    >>> print(isinstance(d1,Person))  #使用isinstance判断p1这个实例是不是Person实例化来的,这个d1是Dog实例化的。
    False
    >>> print(isinstance(d1,(Person,Dog)))  #可以同时判断多个,只要属于其中一个就可以。
    True

    封装变量:

    类就是一个独立存放变量的空间与属性查找。

    >>> class Person:        #本身是一个独立的空间
    	var2 = '变量2'   #赋值语句,将变量封装在这个类空间里(封装变量)
    	pass
    
    >>> Person.var1 = '变量1'    #这种方式使用的少
    >>> print(Person.var1)
    变量1
    >>> print(Person.var2)       #也可以是
    变量2
    >>>  

    属性查找规则:

    属性就是封装在“实例”里面的变量,表征了实例的特点或特征。

    查找变量时,先在实例中查找,然后再到类里面去查找(先实例再类)。

    >>> p =Person()       #实例也是一个独立的变量空间
    >>> print(p.var2)     #尽管这个实例 p 里面没有变量 var2,但是这个实例也可以看到对应类里面封装的变量。
    变量2
    >>> 
    
    >>> class Person:
    	var2 = '变量2'
    	
    >>> p = Person()
    >>> p.var2 = '变量'
    >>> print(p.var2)     #它会打印 '变量',而不是 '变量2',因为它查找var2时先在实例p里面的空间查找,找到之后 就不去类里面查找了。
    变量
    >>> 

    实例也是一个独立存放变量的空间
    每个实例都是一个独立的变量空间。不同实例之间的空间互相不可见

    >>> class Person:      #定义一个类,里面没有任何变量。
    	pass
    
    >>> p1 = Person()   #实例化对象 p1
    >>> p2 = Person()   #实例化对象 p2
    >>> p1.var1 = '变量1'   #实例 p1 里面添加一个变量 var1
    >>> p2.var2 = '变量2'   #实例 p2 里面添加一个变量 var2
    >>> print(p1.var1)      #变量 var1 在实例 p1 这个空间里。
    变量1  
    >>> print(p1.var2)     #变量 var2 不在实例p1这个空间里。然后它会去Person类里面去找,所以最终报错是 ”提示类的问题“
    Traceback (most recent call last):
      File "<pyshell#52>", line 1, in <module>
        print(p1.var2)
    AttributeError: 'Person' object has no attribute 'var2'
    >>> 

    一个“实例”的“特征”(注意:不是类的特征),就是“属性”
    小明是人,tom也是人。但是小明是小明,tom是tom。

    >>> class Person:    
    	pass
    
    >>> p1 = Person()       #实例化对象p1,每个实例的属性是不同的。如:每个人的姓名和年龄不同。
    >>> p2 = Person()
    >>> p1.name = '小明'    #实例p1的特征 name
    >>> p2.name = 'tom'
    >>> p1.age = 18         #实例p1的特征 age
    >>> p2.age = 25
    >>> 
    

    实例方法:

    就是封装在类里的一种特殊的函数。

    >>> class Person:    #定义一个类
    	def func():        #在类中封装一个函数
    		print('Just do a test!')
    
    		
    >>> Person.func()    #通过变量空间的方式调用函数。使用类调用函数不会报错,不会把类当作参数传到函数中。
    Just do a test!
    >>> p = Person()     #声明一个实例
    >>> p.func()         #通过实例调用函数,结果会报错,因为实例调用封装在类里面的函数时会把实例自己 "p" 当作一个参数传到函数func()里面去,结果就是 "func(p)"
    Traceback (most recent call last):
      File "<pyshell#67>", line 1, in <module>
        p.func()         #通过实例调用函数
    TypeError: func() takes 0 positional arguments but 1 was given
    >>> 
    

    使用实例调用函数:

    通过实例调用函数时,会把实例本身当成一个参数传入到封装在类中的函数。如:p.fun(),最终结果是fun(p). 

    如果使用类直接调用函数,是不会把类自己当成一个参数传入到函数中。

    >>> class Person:
    	def func(a): 
    		print(a)      #打印出参数,方便鉴定这个参数是啥?
    
    		
    >>> p = Person()      #实例化对象p
    >>> p.func(123)       #按照正常思维,调用函数func(a)时应该传个参数进去;结果却报错?这是因为使用实例p调用函数func(a)时,
    它会
    实例 p 当成第一个参数参数,传入到函数func(a)中。
    Traceback (most recent call last): File "<pyshell#91>", line 1, in <module> p.func(123) TypeError: func() takes 1 positional argument but 2 were given >>> >>> p.func() #使用实例 p 调用函数func(a)时,它会把自己当成第一个参数,传入到函数func(a)中。 <__main__.Person object at 0x0000029252E5CCF8> >>> print(p) #验证这个参数是不是实例p。 <__main__.Person object at 0x0000029252E5CCF8>
    >>> class Person:
    	def func(a):
    		print(id(a))  #打印出参数的 id
    
    		
    >>> p = Person()   #实例化一个对象 p
    >>> p.func()       #使用实例p 调用函数func(a)
    2827479273312
    >>> print(id(p))   #单独打印实例p 的id,发现和函数参数里面的id 一样;说明实例p在调用函数func(a)时,把自己当成第一个参数传入到函数。
    2827479273312
    >>> Person.func()   #使用类调用函数func(a)时,类不会把自己当成参数传入到函数中,所以报错缺少参数。通过类调用函数和普通调用函数是一样的。
    Traceback (most recent call last):
      File "<pyshell#85>", line 1, in <module>
        Person.func()
    TypeError: func() missing 1 required positional argument: 'a'
    
    >>> Person.func(123)  #使用类调用函数func(a)时,手动传个参数就不会报错。
    1450736928
    

    如何利用实例调用函数时,会自动把自己当成第一个参数传入到函数里?

    >>> class Person:
    	def eat(a):
    		print(a.name,'在eating...')    #注意这里的a.name,其实就是实例的属性。
    
    		
    >>> p1 =Person()      #实例化对象p1
    >>> p1.name = '小明'  #实例p1的属性
    >>> p2 =Person()
    >>> p2.name = '花花'
    >>> p1.eat()    #使用实例p1调用函数 eat(a),它会自动把p1当成第一个参数传入到函数eat(a)中。最终是eat(p1)。所以a.name就是p1.name
    小明 在eating...
    >>> p2.eat()
    花花 在eating...
    >>> 
    

    “实例方法” 的调用过程:

    实例.方法(参数)

    .方法(实例,参数)

    self:

    因为实例调用函数时会把自己当成第一个参数传进函数func(),所以这里第一个参数的变量名就使用约定俗成的 self

    >>> class Person:
    	def func(self,w):    #因为实例调用函数时会把自己当成第一个参数传进函数func(),所以这里第一个参数的变量名就使用约定俗成的 self
    		print(self.name,'在eating:',w)
    
    		
    >>> p1 =Person()        #实例化对象 
    >>> p1.name = '小明'    #实例p1的属性
    >>> p1.func('apple')    #使用实例.方法(参数)调用实例方法。
    小明 在eating: apple
    >>> Person.func(p1,'apple')  #使用类.方法(实例,参数)调用实例方法。
    小明 在eating: apple
    >>> 
    

      

     

  • 相关阅读:
    Java实现文件夹下文件实时监控
    JAVA读取文件夹大小
    Java获取Linux上指定文件夹下所有第一级子文件夹
    自定义日志框架实现
    Node爬取简书首页文章
    NodeJS多进程
    NodeJS 连接接MySQL
    NodeJS Web模块
    NodeJS 模块&函数
    NodeJS Stream流
  • 原文地址:https://www.cnblogs.com/longxd/p/8732661.html
Copyright © 2011-2022 走看看