zoukankan      html  css  js  c++  java
  • Python-Basis-15th

    周五,晴,记录生活分享点滴

    参考博客:https://www.cnblogs.com/wupeiqi/p/4766801.html

    Pyhton版本:3.5

     面向对象(进阶)

    类的成员

    字段

    普通字段

    保存在对象中,执行只能通过对象访问

    class Province:
        country = '中国'  # 静态字段,属于类
    
        def __init__(self, name):
            self.name = name  # 普通字段,属于对象
    
    henan = Province('河南')  # 访问河南,需要通过对象访问字段
    henan.name
    henan.name = "河南南" # 把内部的对象修改了

    静态字段

    保存在类中, 执行可以通过对象访问,也可以通过类访问

    class Province:
        country = '中国'  # 静态字段,属于类
    
        def __init__(self, name):
            self.name = name  # 普通字段,属于对象
    
    hebei = Province('河北')
    hebei.name  # 静态对象可以通过对象访问,
    
    print(hebei.country)  # 静态对象也可以通过类访问

    存储方式

    小结:

    • 静态字段在内存中只保存一份
    • 普通字段在每个对象中都要保存一份

    应用场景:

    • 通过类创建对象时,如果每个对象都具有相同的字段,那么就使用静态字段

    方法

    种类

    普通方法,保存在类中,由对象来调用;至少一个self参数:将对象赋值给参数self

    类方法,保存在类中,由类直接调用;至少一个cls参数:将当前类赋值给cls

    静态方法,保存在类中,由类直接调用;无默认参数

    class Foo:
    
        def __init__(self, name):
            self.name = name
    
        def ord_func(self):
            """ 定义普通方法,至少有一个self参数 """
    
            # print self.name
            print '普通方法'
    
        @classmethod
        def class_func(cls):
            """ 定义类方法,至少有一个cls参数 """
    
            print '类方法'
    
        @staticmethod
        def static_func():
            """ 定义静态方法 ,无默认参数"""
    
            print '静态方法'
    
    
    # 调用普通方法
    f = Foo()
    f.ord_func()
    
    # 调用类方法
    Foo.class_func()
    
    # 调用静态方法
    Foo.static_func()

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

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

    应用场景

    如果对象中需要保存一些值,执行某功能时,需要使用对象中的值 ---> 普通方法
    不需要任何对象中的值 ---> 静态方法

    属性

    属性是普通方法的变种

    属性的基本使用

    # ############### 定义 ###############
    class Foo:
    
        def func(self):
            pass
    
        # 定义属性
        @property
        def prop(self):
            pass
    # ############### 调用 ###############
    foo_obj = Foo()
    
    foo_obj.func()
    foo_obj.prop   #调用属性

    小结:

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

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

    调用时,无需括号
               方法:foo_obj.func()
               属性:foo_obj.prop

    实例

    对于主机列表页面,每次请求不可能把数据库中的所有内容都显示到页面上,而是通过分页的功能局部显示,所以在向数据库中请求数据时就要显示的指定获取从第m条到第n条的所有数据(即:limit m,n),这个分页的功能包括:

    • 根据用户请求的当前页和总数据条数计算出 m 和 n
    • 根据m 和 n 去数据库中请求数据 
    # ############### 定义 ###############
    class Pager:
        
        def __init__(self, current_page):
            # 用户当前请求的页码(第一页、第二页...)
            self.current_page = current_page
            # 每页默认显示10条数据
            self.per_items = 10 
    
    
        @property
        def start(self):
            val = (self.current_page - 1) * self.per_items
            return val
    
        @property
        def end(self):
            val = self.current_page * self.per_items
            return val
    
    # ############### 调用 ###############
    
    p = Pager(1)
    p.start 就是起始值,即:m
    p.end   就是结束值,即:n

    类成员的修饰符

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

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

    私有成员和公有成员的定义不同

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

    class C:
     
        def __init__(self):
            self.name = '公有字段'
            self.__foo = "私有字段"

    私有成员和公有成员的访问限制不同

    静态字段

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

    class C:
    
        name = "公有静态字段"
    
        def func(self):
            print C.name
    
    class D(C):
    
        def show(self):
            print C.name
    
    
    C.name         # 类访问
    
    obj = C()
    obj.func()     # 类内部可以访问
    
    obj_son = D()
    obj_son.show() # 派生类中可以访问

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

    class C:
    
        __name = "私有静态字段"
    
        def func(self):
            print C.__name
    
    class D(C):
    
        def show(self):
            print C.__name
    
    
    C.__name       # 类访问            ==> 错误
    
    obj = C()
    obj.func()     # 类内部可以访问     ==> 正确
    
    obj_son = D()
    obj_son.show() # 派生类中可以访问   ==> 错误

    普通字段

    公有普通字段:对象可以访问;类内部可以访问;派生类中可以访问

    class C:
        
        def __init__(self):
            self.foo = "公有字段"
    
        def func(self):
            print self.foo  # 类内部访问
    
    class D(C):
        
        def show(self):
            print self.foo # 派生类中访问
    
    obj = C()
    
    obj.foo     # 通过对象访问
    obj.func()  # 类内部访问
    
    obj_son = D();
    obj_son.show()  # 派生类中访问

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

    class C:
        
        def __init__(self):
            self.__foo = "私有字段"
    
        def func(self):
            print self.foo  # 类内部访问
    
    class D(C):
        
        def show(self):
            print self.foo # 派生类中访问
    
    obj = C()
    
    obj.__foo     # 通过对象访问    ==> 错误
    obj.func()    # 类内部访问      ==> 正确
    
    obj_son = D();
    obj_son.show()  # 派生类中访问  ==> 错误

    不推荐:强制访问私有字段,可以通过 【对象._类名__私有字段名 】访问(如:obj._C__foo)

    类的特殊成员

    __init__

    条件:类()   自动执行

    class Foo:
    
        def __init__(self, name):
            self.name = name
            self.age = 23
    
    obj = Foo('chung') # 自动执行类中的 __init__ 方法 

    __call__

    条件:对象() or 类()()   自动执行

    class Foo:
    
        def __init__(self):
            pass
        
        def __call__(self, *args, **kwargs):
            print '__call__'
    
    obj = Foo() # 执行 __init__
    obj()       # 执行 __call__

    __int__

    条件:int(对象)   获取返回值并赋值给这个对象

    class Foo:
    
        def __init__(self):
            pass
    
        def __int__(self):
            return 1111
    
    obj = Foo()
    
    
    r = int(obj)  # int,对象,自动执行对象的 __int__方法,并将返回值赋值给int对象
    print(r)
    # 输出:1111

    __str__

    条件:str()   执行str时调用的

    class Foo:
    
        def __str__(self):
            return 'chung'
    
    obj = Foo()
    print obj
    # 输出:chung 

    __add__、__del__

    class Foo:
    
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def __add__(self, other):# self = obj1(alex,19); other = obj2(eric,66)
    
            # return self.age + other.age     # (1)自定义返回obj1的19和obj2的66
            # return Foo('tt',99)             # (2)自定义返回'tt',99的对象
            return Foo(obj1.name, other.age)  # (3)自定义返回obj1的名字和obj2的年龄
    
        def __del__(self):
            print('析构方法')  # 当建立对象被销毁时,自动执行
    
    obj1 = Foo('alex', 19)
    obj2 = Foo('eirc', 66)
    
    r = obj1 + obj2
    # 两个对象相加时,自动执行第一个对象的__add__方法,并且将第二个对象当作参数传递进入
    print(r, type(r))

    __dict__

    获取类或对象中的所有成员

    class Province:
    
        country = 'China'
    
        def __init__(self, name, count):
            self.name = name
            self.count = count
    
        def func(self, *args, **kwargs):
            print 'func'
    
    # 获取类的成员,即:静态字段、方法、
    print Province.__dict__
    # 输出:{'country': 'China', '__module__': '__main__', 'func': <function func at 0x10be30f50>, '__init__': <function __init__ at 0x10be30ed8>, '__doc__': None}
    
    obj1 = Province('HeBei',10000)
    print obj1.__dict__
    # 获取 对象obj1 的成员
    # 输出:{'count': 10000, 'name': 'HeBei'}
    
    obj2 = Province('HeNan', 3888)
    print obj2.__dict__
    # 获取 对象obj1 的成员
    # 输出:{'count': 3888, 'name': 'HeNan'}

    __getitem__、__setitem__、__delitem__

    用于索引操作,如字典。分别表示获取、设置、删除数据

    class Foo(object):
     
        def __getitem__(self, key):
            print '__getitem__',key
     
        def __setitem__(self, key, value):
            print '__setitem__',key,value
     
        def __delitem__(self, key):
            print '__delitem__',key
     
     
    obj = Foo()
     
    result = obj['k1']      # 自动触发执行obj对象的类中的 __getitem__方法,k1当作参数传给key
    obj['k2'] = 'chung'   # 自动触发执行 __setitem__
    del obj['k1']           # 自动触发执行 __delitem__
    class Foo:
    
        def __init__(self, name,age):
            self.name = name
            self.age = age
    
        def __getitem__(self, item):
            # return item+10
            # 如果item是基本类型:int,str,索引获取
            # slice对象的话,切片
            if type(item) == slice:
                print('调用者希望内部做切片处理')
            else:
                print(item.start)
                print(item.stop)
                print(item.step)
                print('调用者希望内部做索引处理')
    
        def __setitem__(self, key, value):
            print(key,value)
    
        def __delitem__(self, key):
            print(key)
    
    li = Foo('chung', 18)
    
    li[123]    # 索引处理
               # 如果是单独的值,传递的参数是int或string类型
    
    li[1:4:2]  # 切片处理
               # 如果是[1:]格式,传递的参数是slice类型
    
    li[1:3] = [11,22]  # 调用的是__setitem__
    
    del li[1:3]        # 调用的是__delitem__
    切片、索引操作

    __iter__ 

    用于迭代器,之所以列表、字典、元组可以进行for循环,是因为类型内部定义了 __iter__ 

    class Foo:
    
        def __init__(self, name,age):
            self.name = name
            self.age = age
    
        def __iter__(self):
            return iter([11,22,33])  # 1、执行li对象的类中的 __iter__方法,并获取其返回值
    li = Foo('alex', 18)
    
    for i in li:  # 2、循环上一步中返回的对象(对象iter的返回值)
        print(i)
        
    # 关于迭代器的几点:
    # 如果类中有 __iter__ 方法,创建的对象叫可迭代对象
    # 可迭代对象.__iter__() 方法的返回值是迭代器
    # for 循环,遇到迭代器,执行next
    # for 循环,遇到可迭代对象,可迭代对象.__iter__()方法,获取迭代器,执行next

    __metaclass__、__new__ 

    1. Python中一切事物都是对象

    2. class Foo:
            pass
        obj = Foo()
        # obj是对象,Foo类
        # Foo类也是一个对象,type的对象

    3. 类都是type类的对象 type(..)

        “对象”都是类的对象 类()

    # 注释解析版
    
    class MyType(type):
        def __init__(self, what, bases = None, dice = None):  # self=Foo
            super(MyType, self).__init__(what, bases, dict)
            
    
        def __call__(self, *args, **kwargs):  # self=Foo类
            obj = self.__new__(self, *args, **kwargs)  # 第二阶段第二步:执行Foo的__new__方法
            # obj因为下面的__new__返回,所以obj是Foo的对象
            self.__init__(obj)  # 第二阶段第三步:self是Foo,把obj传过来
    
    
    class Foo(object, metaclass = MyType):  # 第一阶段:执行MyType的__init__方法
        
        def __init__(self, name):
            self.name = name
    
        def __new__(cls, *args, **kwargs):
            return object.__new__(cls, *args, **kwargs)  # 真正创建对象的是这一句  # cls指创建了Foo的对象
    
    
    obj = Foo()  # 第二阶段第一步:执行MyType的__call__方法
  • 相关阅读:
    关于返回上一页功能
    Mybatis Update statement Date null
    SQLite reset password
    Bootstrap Validator使用特性,动态(Dynamic)添加的input的验证问题
    Eclipse使用Maven2的一次环境清理记录
    Server Tomcat v7.0 Server at localhost failed to start
    PowerShell一例
    Server Tomcat v7.0 Server at libra failed to start
    商标注册英语
    A glance for agile method
  • 原文地址:https://www.cnblogs.com/chungzhao/p/13047933.html
Copyright © 2011-2022 走看看