• python 3 基础之 类和实例 的 属性和方法(类的属性和方法的重写、调用、私有、修改)


    1、类的属性和方法的重写、调用、私有、修改

      1.1、重写:子类重写父类同名属性和方法

        如果两个子类和父类的方法名和属性相同,默认使用子类的,子类虽然方法名和属性与父类相同,但是进行了修改,使用子类的方法和属性做子类独有的事情,这就叫做子类重写父类同名属性和方法

    # 定义三个类,一个子类继承两个父类
    class R(object):
        # 类的属性
        def __init__(self):
            self.name = '父类R'
        # 类的方法
        def Xinxi(self):
             print('学生的基本资料:名字:%s' % self.name)
    class X(object):
        def __init__(self):
            self.name = '父类X'
        def Xinxi(self):
            print('学生的基本资料:名字:%s' % self.name)
    class G(R,X):
        def __init__(self):
            self.name = '子类独有'
        def Xinxi(self):
            print('只需要名字:%s' % self.name)
    xiaoming = G() # 子类和父类有同名的属性
    xiaoming.Xinxi()# 子类和父类有同名的方法,但子类做自己独有的事情

      1.2、子类调用父类同名的属性和方法

        在子类中新建一个子类的方法,方法内容调用父类的方法,然后子类调用对应的方法,如此间接达到子类调用父类方法的目的

    # 定义三个类,一个子类继承两个父类
    class R(object):
        # 类的方法
        def Xinxi(self):
             print('学生的基本资料:名字:R')
    class X(object):
        def Xinxi(self):
            print('学生的基本资料:名字:X')
    class G(R,X):
        def Xinxi(self):
            print('只需要名字:G')
        def Xxinxi(self):
            X.Xinxi(self)
        def Rxinxi(self):
            R.Xinxi(self)
    # 实例化对象,自动执行子类的__init__方法
    xiaoming = G()
    # 调用本类的实例方法: 子类和父类同名的方法,但子类做自己独有的事情
    xiaoming.Xinxi()
    # 进入实例方法去调用父类X、R的方法
    xiaoming.Xxinxi()
    xiaoming.Rxinxi()

      当然,不同名的父类方法,子类继承后可以直接调用

      1.3、通过super()来调用父类方法

        super()通过子类调用当前父类的方法,super默认会调用第一个父类的方法(适用于单继承的多层继承 或者只想使用第一个父类的方法)

    class R(object):
        # 类的方法
        def Xinxi(self):
             print('学生的基本资料:名字:R')
    class X(object):
        def Xinxi(self):
            print('学生的基本资料:名字:X')
    class G(X,R):
        def Xinxi(self):
            # 调用父类的方法
            print('只需要名字:G')
            R.Xinxi(self)
            X.Xinxi(self)
        def all_Xinxi(self):
            super().Xinxi()
    wan = G()
    # 调用父类方法
    wan.all_Xinxi()

      1.4、私有属性和私有方法

         Python是以属性命名方式来区分,如果在属性和方法名前面加了2个下划线'__',则表明该属性和方法是私有权限,否则为公有权限

        类的私有属性和 私有方法,都不能通过对象直接访问,但是可以在本类内部访问;

        类的私有属性 和 私有方法,都不会被子类继承,子类也无法访问

        私有属性 和 私有方法 往往用来处理类的内部事情,不通过对象处理,起到安全作用。

      私有属性和方法示例:

    class Master(object):
        # 构造方法
        def __init__(self):
            self.kongfu = '古法配方'
            # 添加一个属性
            # 如果一个属性的名字开头是两个下划线,代表此属性是私有的
            self.__money = 1000
        # 制作煎饼果
        def make_cake(self):
            print('古法煎饼果')
            print(self.__money)#私有属性只能在类的里面使用
            self.__print()#私有方法可以在类的内部使用
        # 定义一个私有方法
        def __print(self):
            print('这是私有方法')
    lishifu = Master()
    print(lishifu.kongfu)
    # 若一个属性私有后,就不能使用对象调用此属性(私有属性不能在类的外面使用)
    # print(lishifu.__money)
    lishifu.make_cake()
    # lishifu.__print()#这是私有方法,不能调用
    class Prentice(Master):
        pass
    damao = Prentice()
    print(damao.kongfu)
    damao.make_cake()
    # 结论:子类继承父类,若父类属性或方法私有后,将不会被继承,只能在父类里使用

      1.5、修改私有属性的值

      修改私有属性的值一般有两种方法:

        直接修改:对象名 . 属性名 = 新数据

        通过两个方法间接修改:对象名 . 方法名(新数据)

      如下代码,属于间接修改属性的值

    # 自定义一个人类
    class person(object):
        def __init__(self):
            self.name = '小明'
            self.__age = 20#私有属性
        # 定义一个方法(获取属性的值,一般方法中使用get)
        def get_age(self):#用于返回一个私有属性的值
            return self.__age
        # 定义一个方法,对属性赋值的时候一般方法中使用set
        def set_age(self,new_age):
            self.__age = new_age
    xiao = person()
    print(xiao.get_age())#使用对象调用私有属性完成打印age的值
    xiao.set_age(33)#使用对象设置属性的值
    print(xiao.get_age())

     2、类属性和实例属性

      顾名思义,类属性就是类对象所拥有的属性,它被所有类对象实例对象所共有,在内存中只存在一个副本,对于公有的类属性,在类外可以通过类对象实例对象访问

      2.1、类属性

        类属性的好处:每定义个对象实例属性会占用一份内存,而类属性只占用一份内存,使用类属性可以节约空间提高性能,为后期业务需求更改,方便开发

        访问:不能在类外通过实例对象访问私有类属性,可以访问共有的类属性

    class People(object):
        name = 'Tom'  # 公有的类属性
        __age = 12  # 私有的类属性
    
    p = People()
    
    print(p.name)  # 正确
    print(People.name)  # 正确
    print(p.__age)  # 错误,不能在类外通过实例对象访问私有的类属性
    print(People.__age) # 错误,不能在类外通过类对象访问私有的类属性

      2.2、实例属性

    class People(object):
        address = '山东'  # 类属性
        def __init__(self):
            self.name = 'xiaowang'  # 实例属性
            self.age = 20  # 实例属性
    
    p = People()
    p.age = 12  # 实例属性
    print(p.address)  # 正确
    print(p.name)  # 正确
    print(p.age)  # 正确
    
    print(People.address)  # 正确
    print(People.name)  # 错误
    print(People.age)  # 错误

      2.3、通过实例去修改类属性

    class People(object):
        country = 'china' #类属性
    
    print(People.country)
    p = People()
    print(p.country)
    p.country = 'japan' 
    print(p.country)  # 实例属性会屏蔽掉同名的类属性
    print(People.country)
    del p.country  # 删除实例属性
    print(p.country)

    运行结果:

    china
    china
    japan
    china
    china

      如果需要在类外修改类属性,必须通过类对象去引用然后进行修改。如果通过实例对象去引用,会产生一个同名的实例属性,这种方式修改的是实例属性,不会影响到类属性,并且之后如果通过实例对象去引用该名称的属性,实例属性会强制屏蔽掉类属性,即引用的是实例属性,除非删除了该实例属性

      2.4、实例属性和方法的开辟空间规则

        创建对象占用内存地址,对象的属性也另外占用内存地址,对象占用的地址与对象属性占用的地址不一样(同一个类创建的对象,其属性的占用地址不一样)

        不同的对象,但是调用的对象、方法的id相同(地址相同),因为调用的是同一个方法

        创建不同对象表达的是不同的人,其属性特征是不同的,但方法相同,因为方法中有个形参self可以区分是哪个对象调用的

    class Person(object):
        def __init__(self,name):
            self.name = name
        def eat(self):
            print('人会吃饭')
    # 使用一个类创建一个对象后,就会占用内存地址(空间)
    # 用id查看空间地址,如print(id(xiaoming))
    # 对象的内存地址不同,代表各占一个空间
    xiaoming = Person('小明')
    print(id(xiaoming))
    print(id(xiaoming.name))
    print(id(xiaoming.eat()))
    
    xiaohong = Person('小红')
    xiaohong.eat()
    print(id(xiaohong.name))
    print(id(xiaohong))#创建两个对象后需要分别开辟空间,占用内存较多
    print(id(xiaohong.eat()))

      2.5、类方法和静态方法

        2.5.1、类方法

      类方法是类对象所拥有的方法,需要用修饰器@classmethod来标识其为类方法

      对于类方法,第一个参数必须是类对象,一般以cls作为第一个参数(当然可以用其他名称的变量作为其第一个参数,但是大部分人都习惯以'cls'作为第一个参数的名字,就最好用'cls'了),能够通过实例对象和类对象去访问。

      实例方法的第一个参数是实例对象self,那么通过self引用的可能是类属性、也有可能是实例属性(这个需要具体分析),不过在存在相同名称的类属性和实例属性的情况下,实例属性优先级更高。

      静态方法中不需要额外定义参数,因此在静态方法中引用类属性的话,必须通过类实例对象来引用

    class People(object):
        country = 'china'
    
        #类方法,用classmethod来进行修饰
        @classmethod
        def get_country(cls):
            return cls.country
    
    p = People()
    print(p.get_country())    #可以用过实例对象引用
    print(People.get_country())    #可以通过类对象引用

        2.5.2、类方法对类属性进行修改

    class People(object):
        country = 'china'
    
        #类方法,用classmethod来进行修饰
        @classmethod
        def get_country(cls):
            return cls.country
    
        @classmethod
        def set_country(cls,country):
            cls.country = country
    
    p = People()
    print(p.get_country())   #可以用过实例对象访问
    print(People.get_country())    #可以通过类访问
    
    p.set_country('japan')   
    
    print(p.get_country())
    print(People.get_country())

      结果显示在用类方法对类属性修改之后,通过类对象和实例对象访问都发生了改变

        2.5.3、静态方法(了解)

          需要通过修饰器@staticmethod来进行修饰,静态方法不需要多定义参数,可以通过对象和类来访问。

    class People(object):
        country = 'china'
    
        @staticmethod
        #静态方法
        def get_country():
            return People.country
    
    p = People()
    # 通过对象访问静态方法
    p.get_contry()
    
    # 通过类访问静态方法
    print(People.get_country())
  • 相关阅读:
    谈谈-开源数据库LitePal
    谈谈-Android-PickerView系列之封装(三)
    谈谈-Android-PickerView系列之源码解析(二)
    谈谈-Android-PickerView系列之介绍与使用(一)
    谈谈-ConstraintLayout完全解析
    问题解决-Failed to resolve: com.android.support.constraint:constraint-layout:1.0.0-alpha7
    谈谈-BaseAdapter的封装
    谈谈-使用SparseArray和ArrayMap代替HashMap
    Spring 集成Redis Cluster模式
    Redis三种集群模式-Cluster集群模式
  • 原文地址:https://www.cnblogs.com/will-wu/p/13265475.html
Copyright © 2020-2023  润新知