进阶面向对象——类的成员

类的成员可以分为三大类:字段、方法、属性。

           

  @:所有成员中,只有普通字段的内容保存在对象中,即:根据此类创建了多少对象,在内存中就有多少普通字段。而其他的成员都是保存在类中的,即:无论对象的多少,在内存中只创建一份。

 

一、字段:(普通字段和静态字段)

  1、普通字段:属于对象

  2、静态字段:属于类

class Yitian:
    
    #静态字段
    user = "张无忌"
    def __init__(self,name):

        #普通字段
        self.name = name

#直接访问普通字段
obj = Yitian("明教")
print(obj.name)

#直接访问静态字段
print(Yitian.user)

@普通字段需要通过对象来访问,静态方法通过类访问。(两者的归属不同)

由图可知: 

  静态字段在内存中只保存一份

  普通字段在每个对象中都要保存一份

class Yitian:

    #静态字段
    user = "张无忌"
    def __init__(self,name):

        #普通字段
        self.name = name

#直接访问普通字段
obj1 = Yitian("明教")
obj2 = Yitian("峨眉")
print(obj1.name)
print(obj2.name)   #增加了一个对象”峨眉“

#直接访问静态字段
Yitian.user = "周芷若"  #改变了静态字段  结果:周芷若
print(Yitian.user)      #最终结果:周芷若

 

应用的场景:通过类创建对象时,如果每个对象都具有相同字段,那么就用静态字段。

 

二、方法:(普通方法、静态方法、类方法-->在内存中都归属于类,调用方式不同)

  1、普通方法:

    由对象调用,至少一个self参数,执行普通方法时,自动将调用该方法的对象赋值给self。

  2、类方法:

    由类方法调用,至少一个cls参数,执行方法时,自动将调用该方法的类复制给cls.

  3、静态方法: 

     由类调用,无默认值参数。

class Foo:
    def __init__(self,name):
        self.naem = name

    def ord_func(self):
        '''定义一个普通方法,至少有一个self参数'''
        print(self.naem)
        print("普通方法")

    @classmethod
    def class_func(cls):
        '''定义一个类方法,至少一个cls参数'''
        print("类方法")

    @staticmethod
    def static_func():
        '''定义一个静态方法,无默认值参数'''
        print("静态方法")
#调用普通方法
f = Foo()
f.ord_func()

#调用类方法
Foo.class_func()

#调用静态方法
Foo.static_func()

@区别:

  相同点:对于所有的方法而言,均属于类(非对象)中,所以在内存中也只保存一份。

  不同点:方法调用者不同、调用方法时自动传入的参数不同。

 

三、属性:

  1、属性的基本使用:  

#==========定义=================
class Doo:
    def func(self):
        pass

    #定义属性
    @property
    def prop(self):
        pass
#=========调用===============
doo_obj = Doo()
doo_obj.func()
doo_obj.prop   #调用属性

@定义属性的注意事项:

  定义时,在普通方法的基础上添加@property装饰器

  定义时,属性仅有一个self参数

  调用时,无需括号

    方法:obj.func()

    属性:obj.prop   #没有括号

      属性存在的意义是:访问属性时可以制造出和访问字段完全相同的假象

      属性由方法变种而来,如果python中没有属性,方法完全可以代替其功能。

#例:  分页显示请求的页面的数据
class Pager:
    def __init__(self,current_page):
        #用户当前请求的页码
        self.current_page = current_page
        #每页默认显示10条数据
        self.per_intems = 10

    @property
    def start(self):
        val = (self.current_page - 1) * self.per_intems
        return val
    @property
    def end(self):
        val = self.current_page * self.per_intems
        return val
#调用
p = Pager(10)
print(p.start)
print(p.end)

@python属性的功能是:属性内部进行一系列的逻辑计算,最终将计算结果返回

 

  2、属性的两种定义方式

     (1)、装饰器:在方法上应用装饰器    

  装饰器方式:在类的普通方法上应用@property装饰器

    经典类:具有一种@property装饰器

#==========定义=========
class Goods:
    @property
    def price(self):
        return "张无忌"
# ======调用==========
obj = Goods()
result = obj.price  #自动执行@property修饰方法,并获取方法的返回值。
print(result)

    新式类:具有三种@property装饰器

#======定义=======
class Goods:
    @property
    def price(self):
        print("张无忌")
    @price.setter
    def price(self,value):
        print("周芷若")
        # print(value)
    @price.deleter
    def price(self):
        print("赵敏")
# =====调用============
obj = Goods()
obj.price  #自动执行@property修饰的price方法,并获取方法的返回值
obj.price = 123 #自动执行@property.setter修饰的price方式,并将123赋值给方法的参数
del obj.price #自动执行@price.deleter修饰的price方法

@  经典类中的属性只有一种访问方式,其对应被@property修饰的方法

   新式类中的属性有三种访问方式,并分别对应了三个被@property、@方法名.setter、@方法名.deleter修饰的方法。(由于新式类中具有三种访问方式,根据他们几个属性访问特点,分别将三个方法定义为对同一个属性:获取、修改、删除)

class Goods:
    def __init__(self):
        #原价
        self.original_price = 10
        #折扣
        self.discount = 0.8
    @property
    def price(self):
        #实际价格 = 原价 * 折扣
        new_price = self.original_price * self.discount
        return new_price
    @price.setter
    def price(self,value):
        self.original_price = value
    @price.deleter
    def price(self):
        del self.original_price

obj = Goods()
print(obj.price)    #获取商品价格
update = obj.price = 200   #修改商品原价
print(update)
del obj.price    #删除商品原价

 

    (2)、静态字段:在类中定义值为property对象的静态字段

       当使用静态字段的方式创建属性时,经典类和新式类无区别

class Foo:
    def get_bar(self):
        return "张无忌"
    BAR = property(get_bar)

obj = Foo()
reuslt = obj.BAR   #自动调用get_bar方法,并获取方法的返回值
print(reuslt)

# 结果:张无忌

property的构造方法中有四个参数

  第一个参数是方法名,调用对象.属性 时自动触发执行方法

   第二个参数是方法名,调用对象.属性 =xxx 时自动触发执行方法

  第三个参数是方法名,调用del 对象.属性 时自动触发执行方法

  第四个参数是字符串,调用对象.属性.__doc__,此参数是该属性的描述信息

class Foo:
    def get_bar(self):
        return "张无忌"
    #必须两个参数
    def set_bar(self,value):
        return "set value" + value

    def del_bar(self):
        return "周芷若"

    BAR = property(get_bar,set_bar,del_bar,"description...")

obj = Foo()
obj.BAR            #自动调用第一个参数中定义的方法:get_bar
obj.BAR = "赵敏"   #自动调用第二个参数中定义的方法:set_bar,并将“赵敏”当作参数传入
del Foo.BAR        #自动调用第三个参数中定义的方法:del_bar方法
obj.BAR.__doc__    #自动获取第四个参数中设置的值description...

  由于静态字段方式创建属性具有三种访问方式,我们可以根据他们几个属性的访问特点分别将三个方法定义位获取、修改、删除  

class Googs(object):

    def __init__(self):
        self.original_price = 100  #原价
        self.discount = 0.8        #折扣
        self.WW = 22

    def get_price(self):
        #实际价格 = 原价 * 折扣
        new_price = self.original_price * self.discount
        return new_price
    def set_price(self,value):
        self.original_price = value
    def del_price(self):
        del  self.WW
    PRICE = property(get_price, set_price, del_price, "价格属性描述。。。")
obj = Googs()
print(obj.PRICE)  #获取商品价格
obj.PRICE = 200   #修改商品原价
del obj.PRICE #删除商品原价

  所以在定义属性共有两种方式,分别是【装饰器】和【静态字段】,而【装饰器】方式针对经典类和新式类又有所不同。

 

四、类成员修饰符

  对于每一个类的成员而言都有两种形式:

    共有成员,在任何地方都能访问

    私有成员,只有在类的内部才能访问

  1、私有成员的和共有成员的定义不同

    私有成员命名时,前两个字符时下划线。(特殊成员除外,例如:__init__、__call__、__dict__等)

class Foo:
    def __init__(self):
        self.name = "张无忌"  #公有字段
        self.__age = 20       #私有字段

  2、私有成员和共有成员的访问限制不同:

    (1)、静态字段

      公有静态字段:类可以访问;类内部可以访问,派生类中可以访问

class Foo:
    name = "张无忌"  #公有静态字段
    def func(self): 
        print(Foo.name)
class Doo(Foo):
    def show(self):
        print(Foo.name)

Foo.name    #类访问

obj = Doo()
obj.func()   #内部类可以访问

obj_son = Doo()
obj_son.show()   #派生类中可以访问

      私有静态字段:仅类内部可以访问

class Foo:
    __name = "张无忌"  #私有静态字段
    def func(self):
        print(Foo.__name)
class Doo(Foo):
    def show(self):
        print(Foo.__name)

Foo.name    #类访问   ---错误

obj = Doo()
obj.func()   #内部类可以访问  ---正确

obj_son = Doo()
obj_son.show()   #派生类中可以访问   ---错误

     (2)、普通字段

      共有普通字段:对象可以访问,内部类可以访问、派生类可以访问

class Foo:
    def __init__(self):
        self.foo = "周芷若"  #公有字段
    def func(self):
        print(self.foo)  #类内部访问

class Doo(Foo):
    def show(self):
        print(self.foo)   #派生类中访问
obj = Foo()

obj.foo  #通过对象访问
obj.func()  #类内部访问

obj_son = Doo()
obj_son.show()   #派生类中访问

      私有普通字段:仅类内部可以访问

  @如果想要强制访问私有字段,可以通过[对象._类名__私有字段名]访问,(例如:obj._Foo__foo),不建议强制访问私有成员。

class Foo:
    def __init__(self):
        self.__foo = "周芷若"  #私有字段
    def func(self):
        print(self.__foo)  #类内部访问

class Doo(Foo):
    def show(self):
        print(self.__foo)   #派生类中访问  ---错误
obj = Foo()

obj.foo  #通过对象访问   ---错误
obj.func()  #类内部访问   ---正确

obj_son = Doo()
obj_son.show()   #派生类中访问   ---错误

@方法、属性的访问于上述方式相似,即:私有成员只能子啊类内部是用

@非要访问私有属性的话,可以通过 对象._类__属性名

 

五、类的特殊成员

  1、__doc__

  2、__module__和__class__

  3、__init__

  4、__del__

  5、__call__

  6、__dict__

  7、__str__

  8、__getitem__、__setitem__、__delitem__

  9、__getslice__、__setslice__、__delslice__

  10、__iter__

  11、__new__和__metaclass__

 

  

 

posted @ 2018-08-28 08:33  LW-5208  阅读(224)  评论(0)    收藏  举报