zoukankan      html  css  js  c++  java
  • python-类(1)

     

    ·类(Class)

    笔记:

      Python是一种面向对象(Object Oriented)的编程语言,类(Class)是Python的核心概念。在Python中,不管是列表、字符串、函数和类都是对象

      在面向对象编程(OOP)中,任何一个对象都要包含两个部分:属性(是什么)和方法(能做什么)

    举个例子:小红有某些特征:眼睛大、皮肤白、身材好,这些特征可以比作类中属性;除了特征之外,小红会唱歌、跳舞、弹琴,这些能力可以比作类中的方法:

    def 美女:
        眼睛 = 大
        皮肤 = 白
        身材 = 好
        唱歌()
        跳舞()
        弹琴()

    将美女类实例化

    小红 = 美女()  #小红是一个实例

    针对”小红“这个实例,访问属性和使用方法:

    小红.眼睛        #访问类中的属性
    小红.眼睛 =#修改类中的属性(眼睛由大变小)
    小红.唱歌()     #使用类中的方法

    @类中的基本概念


     创建一个Hello类:

    class Hello(object):                     #在python3中,所有类都是类object的子类;定义类也可以写成 class Hello:或者 class Hello():
        def __init__(self,name='world'):     #初始化函数__init__  
            self.name = name                 #类中的属性
        def get_name(self):                  #类中的函数称作方法。
            return 'hello,{}'.format(self.name)
    
    h = Hello('jimmy')   #实例化类(h是实例对象)
    print(h.name)        #访问类的属性
    print(h.get_name())  #访问类的方法
    print('显示h是Hello的实例:',type(h))  
    print('显示h是Hello的实例:',h.__class__)  
    print('显示h是Hello的实例,类Hello在内存中的地址为(at···):',h)
    打印结果:
    jimmy
    hello,jimmy
    显示h是Hello的实例: <class '__main__.Hello'>
    显示h是Hello的实例: <class '__main__.Hello'>
    显示h是Hello的实例,类Hello在内存中的地址为(at···): <__main__.Hello object at 0x000001A057CE6CC0>

     初始化函数: __init__

    初始化函数意味着实例化时要给name提供一个值,通过__init__执行初始化,让实例具有name的属性。由于类Hello中name参数设有默认值,当没有传入参数时,默认为world。

    在类外,字符串 'Jimmy' 通过初始化函数__init__()中的 name 参数存入内存中,以Hello类型存在,组成一个对象,这个对象和变量h建立引用关系。这个过程也可以理解成这些数据附加到一个实例上,这样就能通过实例以访问属性的方式访问它。

    类中的: Self

    在类中, 如果某个地方(比如类中的方法)想要使用实例化传入的数据,那该怎么办?

    在类中,将所有传入数据都赋值给一个变量,这个变量是在初始化函数__init__中的第一个参数self。它能接收实例化过程中传入的所有数据,这些数据是根据初始化函数后面的参数导入的。很显然,self就是一个实例,准确说法是应用实例,因为它所对应的就是具体的数据。接下来来验证:

    class Hello(object):                    
        def __init__(self,name='world'):  
            self.name = name
         self.address = 'beijing'
    print(self) print(type(self)) def get_name(self): return 'hello,{}'.format(self.name) h = Hello()
    打印结果:
    <__main__.Hello object at 0x0000019FBBBB4E10>
    <class '__main__.Hello'>

    self实例和h实例一样都有属性。self.name是self的属性,值为name,当然也可以写成self.xxx = name也是可以的。self属性的值不一定要从外部传入,也可以在初始化函数中定义,比如self.address = 'beijing'

    在get_name(self)方法中,self是默认的,当类实例化后调用此方法,不需要赋值self能够让return中的语句访问初始函数中传入的值和属性)

    类提供默认的行为,而实例可以看成一个工厂。所谓工厂就是可以用一个模板作出很多产品,而类就是模板,实例就是具体的产品。

    @类属性和实例属性


    类是一个对象,有属性;同样,类实例化后也是一个对象,也有它的属性。通过实例化得到的属性称为实例属性,一般情况下可以通过类来访问属性,也可以通过实例来访问属性。

    class A:
        x = 1
    
    a = A()
    a.x = 5     #更改实例属性
    print('实例属性为:',a.x)
    print('类属性为:',A.x)
    打印结果:
    实例属性为: 5
    类属性为: 1

    实例属性更改了,但类属性没有跟着改变,这是因为类属性不会受实例属性所左右。 

    class A:
        x = 1
    
    a = A()
    A.x = 10   #更改类属性
    print('实例属性为:',a.x)
    print('类属性为:',A.x)
    打印结果:
    实例属性为: 10
    类属性为: 10

    类属性更改了,实例属性也跟着改变了,说明实例属性受类属性所左右。 

    以上所言是指类中的变量引用的是不可变的数据类型(整型、浮点型、字符串、元组),如果引用可变数据类型(字典、列表),数据将发生变化:

    class B:
        x = [1,2,3,4]
    
    b = B()
    b.x.append(5) #实例属性增加一个值5
    print('实例属性:',b.x)
    print('类属性:',B.x)
    打印结果:
    实例属性: [1, 2, 3, 4, 5]
    类属性: [1, 2, 3, 4, 5]

    当变量中引用的是可变数据类型时,类属性和实例属性都能够直接修改这个对象,从而影响另一方的值。

    通过实例和类增加属性:

    class B:
        x = [1,2,3,4]
    
    b = B()
    B.y = 'hello,world!'       #增加一个类属性
    print('实例属性:',b.y) 打印结果: 实例属性: hello,world!

    结果表明:通过类增加一个类属性,实例可以访问到它。

    如果是用实例增加一个实例属性呢?

    class B:
        x = [1,2,3,4]
    
    b = B()
    b.y = 'hello,world!'       #增加一个实例属性
    print('实例属性:',b.y)
    print('类属性:',B.y)
    打印结果:
    实例属性: hello,world!
    Traceback (most recent call last):
      File "test1.py", line 8, in <module>
        print('类属性:',B.y)
    AttributeError: type object 'B' has no attribute 'y'

    结果表明:增加的实例属性可以通过实例访问,如果通过类访问,结果显示类B中没有属性y。

     

    @ 数据流转


    在类的应用中,最广泛的是将类实例化,通过实例来执行各种操作。所以对此过程中的数据流转必须弄明白。

    class Hello(object):                     
        def __init__(self,name='world'):   
            self.name = name               
        def get_name(self):                 
            return 'hello,{}'.format(self.name)
        def get_color(self,color):
            print('My love color is:',color)
            
    h = Hello('jimmy')          
    print(h.get_name())         
    print(h.get_color('red'))
    打印结果:
    hello,jimmy
    My love color is: red
    None                         #由于get_color()方法没有设置返回值,函数默认返回None

     数据流转过程:

    创建实例 h = Hello('jimmy'),h 实例和初始化函数中self对应(self接收实例传入的所有数据);'jimmy'是具体的数据,通过初始化函数中的name参数传给self.name(self是个实例,可以设置它的属性),此时name的值为jimmy。

    类中除初始化函数以外的方法无论有没有定义参数,都要以self开头,这在类中是不能省略的,这表示所有方法都承接self实例对象。也就是实例的属性被带入到每个方法中,如get_name()中的return 'hello,{}'.format(self.name)语句,self.name调用前面已经确定的实例属性数据为jimmy,所以函数返回hello,jimmy。因此,通过self,可以实现数据在类的内部流转。

    如果要把数据从类的内部传到外部,可以通过return语句,由于def get_color():方法没有设置函数返回值,函数默认返回None。

     

    @ 类的命名空间和作用域


    类命名空间

    定义类时,在class语句中的代码都在一个命名空间中执行,即类的命名空间。命名空间是从所定义的命名到对象的映射集合。不同的命名空间可以同时存在但彼此相互独立。

    命名空间因对象不同,可以分为以下几种:

    内置命名空间:

    内置函数的命名空间都属于内置命名空间,因此,可以在程序中直接运行它们。比如print()函数id()函数等拿来就可以直接使用。

    全局命名空间:

    每个模块都有自己的全局命名空间,不同模块的全局命名空间彼此独立;不同模块相同名称的命名空间,因为模块不同而不会相互干扰。

    本地命名空间:

    模块中有类和函数 ,每个类或者函数所定义的命名空间就是本地命名空间。如果函数返回结果或者异常,本地命名空间也将结束。

    各个命名空间的关系(图片来源于网络):

     

    访问命名空间的时候,就按照从里到外的顺序:

    def Duo(x,y):
        name = 'jimmy'
        return locals()
        
    print(Duo('he','llo'))
    打印结果:
    {'x': 'he', 'y': 'llo', 'name': 'jimmy'}

    通过locals()访问本地命名空间的方法,命名空间中的数据存储结构和字典一样;也可以通过globals()访问全局命名空间。

    作用域:是指在python程序中可以直接访问到的命名空间。直接访问意味着访问命名空间中的命名时无需附加任何修饰语。程序按照命名空间从里到外的顺序,搜索相应命名空间能够访问到的作用域。

    def out_t():
        b = 10
        def in_t():
            c= 20
    a = 30

    假设我在def in_t():函数中,c对于我来说就是本地作用域,而a和b不是;如果我在def in_t():函数中新增加一个对象(b = 20),这和def out_t():中的b不会冲突,因为他们的作用域不同。

    接下来我们证实:

    def out_t():
        a = 10
        def in_t():
            a = 20
            print('in_t,a=',a)
        in_t()
        print('out_t,a=',a)
    
    a = 30
    
    print(out_t())
    print('a=',a)
    打印结果:
    in_t,a= 20
    out_t,a= 10
    None
    a= 30

    end~

    ****** 几米花的Python ****** 博客主页:https://www.cnblogs.com/jimmy-share/  欢迎转载 ~
  • 相关阅读:
    .net 调用命令行进行解压缩
    《jQuery实战》第1章 引荐JQuery
    将指定URL文件下载到指定服务器
    Oracle学习笔记
    Spring3 AOP的使用
    Field类使用以及getDeclaredFields方法
    spring 3的使用
    Json数据类型
    RotateAnimation详解
    GsonJava对象生成Json串
  • 原文地址:https://www.cnblogs.com/jimmy-share/p/9853166.html
Copyright © 2011-2022 走看看