zoukankan      html  css  js  c++  java
  • day23 01 类的命名空间

    day23  01 类的命名空间

    一、初识面向对象复习

    定义类:

    class

    函数:方法 动态属性

    变量:类属性 静态属性

    过程:

    (1)_init_方法:初始化:def _init_(self,参数)

      python帮我们创建了一个对象self

      每当我们调用类的时候就会自动触发这个方法

      在_init_方法里面可以对self进行赋值

    self是什么:self拥有属性都属于对象

      在类的内部,self就是一个对象

        比如:someone=person(),someone.walk==person.walk(someone),括号里面就是类里面的walk方法所传的参数self,

                   而且这个参数必须传

    (2)实例化:对象=类(参数是_init_方法的)

      实例==对象 没有区别

      对象查看属性:对象.属性

      对象调用方法:对象.方法名(参数)==类名.方法名(对象名,参数)

    (3)实例:

      求正方形的周长和面积:

    class square:
        def __init__(self,side_len):
            self.side_len_=side_len
        def perimeter(self):
            return self.side_len_*4
        def area(self):
            return  self.side_len_**2
    s=square(6)
    print(s.perimeter())
    print(s.area())

    运行结果:

    24
    36

    为什么计算这个周长和面积要使用类的调用和方法呢?

      正方形不同的地方就是边长不一样,不同的边长的正方形就归为一类

      有了固定的边长,当调用类里面的方法的时候就不需要再传参数了:print(s.perimeter()) , print(s.area())都不需要再传参数

    何为python入门,面向对象入门:

    python 入门:当你见到一个需求,你能翻译成python语言

    面向对象入门:当你见到一个需求,你能分析这个需求适不适合使用面向对象解决,如果适合,你能有一些想法

    二、类和对象的命名空间

    类里面可以定义两种属性:

      静态属性:

      动态属性:

    定义一个类:一种课程course,属性有:老师,课程名字,课程时间,课程费用

    class course:
        language='Chinese'
        def __init__(self,teacher,course_name,period,price):
            self.teacher=teacher
            self.course_name=course_name
            self.period=period
            self.price=price
        def func(self):
            pass
    python=course('李白','python','六个月','10000')
    print(python.teacher)
    print(python.course_name)
    print(python.period)
    print(python.price)
    course.language='English' #直接类名.静态属性是可以修改静态属性的
    print(course.language)
    course.__dict__['language']='English'  #但是使用类的字典形式去修改静态属性是不可能的,会报错
    print(course.language)
    print(python.language) #使用对象调用和查看类下的静态属性是可以的

    运行结果:

    Traceback (most recent call last):
    李白
      File "<encoding error>", line 31, in <module>
    python
    TypeError: 'mappingproxy' object does not support item assignment
    六个月
    10000
    Chinese
    English

    1、为什么对象可以直接调用查看类下的静态属性呢?

    print(python.language)---可以且不会报错

    类下的命名空间有:language, _init_, func
    对象self里面的命名空间有:teacher, course_name, period, price

    类对象指针(内存地址可以有对象的指向类的):可以根据对象属性找到对应的类,但是不能根据类找到对应的对象属性
    python.language:首先会在python里面找,如果找不到就会向对应的类中找,找到了就可以调用查看了
    course.name:是找不到的
    假设多加一门课程linux:
    python=course('李白','python','六个月','10000')
    linux=course('秋白','linux','六个月','10000')

    没有改变类下的静态属性language,然后打印

    print(python.language) 
    print(linux.language)

    是都可以打印出来的,且都是Chinese,而当通过

    course.language='English'

    修改静态属性之后,再次打印

    print(python.language)
    print(linux.language)

    结果也都会随之改变,都会变成English,当只通过对象修改类下的静态属性,在打印也是可以改的,如下:

    python.language='English'
    print(python.language)

    2、对于不可变数据类下的类下属性的操作

    上面的 python.language='English', print(python.language)的改法实际上是在python对象下创建了一个新的language=‘English’,所以再python里面可以找得到,就不会继续往类下面去找,在类下和linux下面(Linux指向的是类的命名空间)并没有创建新的language,类下的language是不可变的数据类下,所以当打印

    print(linux.language)
    print(course.language)

    的结果还是原来的language的结果,即Chinese所以:

    注意:对于不可变的数据类型来说,类变量最好使用类名操作

     3、对于可变的数据类型类下属性的操作

    比如前面的代码中类下的属性如果是: language=['Chinese'],然后按照下面进行修改打印:

    course.language[0]='English'
    print(course.language)
    print(linux.language)
    python.language[0]='English'
    print(python.language)
    print(course.language)
    print(linux.language)
    运行结果:
    ['English']
    ['English']
    ['English']
    ['English']
    ['English']

    此时通过对象名对类下的属性进行修改的时候就可以修改成功了,为什么呢?

    (1)对于course.language[0]='English'的修改

    类下的命名空间里面的language指向一个list的地址,而list的0元素指向的是Chinese的地址,当你通过 course.language[0]='English'

    去修改的时候,并没有改变language指向list,对象指向类的命名空间的过程,所以最后都可以通过对象找得到改变的类下的属性;

    (2)对于python.language[0]='English'的修改

    首先python对象先在自己的命名空间里面找一个可变的数据类型language,找不到就往类的命名空间里面找,因为对象指向类的命名空间,并且可以找到可变的数据类型language,所以在做python里面的修改的时候,类下的也会随之改变

    注意:对于可变数据类型来说,通过对象名修改类下属性是共享的,但是如果不是修改而是直接重新赋值的话是独立的(类似于前面的不可变数据类型通过对象名对类下属性是不能修改的)

     

    4、创建一个类,每实例化一个对象就记录下来,最终所有的对象都共享这个数据

    比较简单的代码:

    class Foo:
        count=0
        def __init__(self):
            Foo.count+=1 #使用类名操作类下属性,对象名调用类下属性的时候,类下属性会随着操作的变化而变化
    f1=Foo()
    f2=Foo()
    print(f1.count)
    print(f2.count)
    f3=Foo()
    print(f1.count) #实例化f3,然后通过对象f1操作类下属性,也是可以的,说明通过类名操作类下属性的结果是共享的

    运行结果:

    2
    2
    3

    这样就能满足每次实例化的时候count就会加一

    5、认识绑定方法

     一个类也是可以没有_init_方法的初始化的,只不过这样每次实例化的时候创建对象字典里面就没有任何值,是一个空的字典,代码如下:

    class Foo:
        def func(self):
            print('func')
    f1=Foo()

    运行结果:为空

    class Foo:
        def func(self):
            print('func')
    f1=Foo()
    print(Foo.func)
    print(f1.func)
    #这里的打印结果<bound method Foo.func of <__main__.Foo object at 0x0000016551112860>>会告诉我们一个绑定方法
    print(f1)

    什么叫做绑定方法呢?

    只有当对象去调用类下的方法的时候,调用方法的时候必须传入就是该对象,这样对象与方法之间就产生了一种绑定的关系,如果用类名调用就不会产生这种绑定关系

    先暂时了解一下,因为后面会讲到类外一种非绑定的方法

    6、包中的_init_

    为什么我们每次导入一个包就会自动调用执行里面的_init_文件?

    因为每次导入一个包 import package====类的实例化过程,包每次被导入就成为一个对象了,所以只要导入就可以使用里面的方法

    比如:

    import time

    time.time

  • 相关阅读:
    Python必须知道的异常处理
    类的内置方法(用实际代码来验证)
    类的三大特性(继承, 封装, 多态)
    面向对象编程代码详解(依赖关系,关联关系,组合关系)
    函数(匿名函数,嵌套函数,高阶函数,装饰器)
    常用模块
    对磁盘文件的操作(文件处理)
    字符编码
    常用数据类型
    编程介绍
  • 原文地址:https://www.cnblogs.com/wxm422562/p/10864928.html
Copyright © 2011-2022 走看看