zoukankan      html  css  js  c++  java
  • Python 面向对象

    类变量的访问限制

    class Data:
        def __init__(self, arg1, arg2):
            self.__arg1 = arg1
            self.__arg2 = arg2
        def print_args(self):
            print(f"arg1:{self.__arg1}, arg2:{self.__arg2}")
    
    data = Data("1", 2)
    data.print_args() # arg1:1, arg2:2
    print(data.__arg1) # 报错 'Data' object has no attribute 'arg1'
    print(data.__arg2) # 报错 'Data' object has no attribute 'arg2'
    

    当变量名为 __arg1 这样的形式时,类的示例就不能直接访问。
    因为 Python 解释器将 __arg1 改成了 _Data__arg1

    data = Data("1", 2)
    print(data._Data__arg1) # 1
    

    获取对象的信息

    对象的类型

    type(data) # __main__.Data
    

    比对对象类型

    isinstance(data, Data) # True
    

    判断是否是函数

    import types
    def my_func():
        ... # 三个点相当于 pass
    
    type(my_func) == types.FunctionType # True
    type(max) == types.BuiltinFunctionType # True
    type(lambda x: x*x) == types.LambdaType # True
    type((x for x in [1, 2, 3])) == types.GeneratorType # True
    

    获取对象的所有属性和方法

    dir(data)
    """
    ['_Data__arg1',
     '_Data__arg2',
     '__class__',
     '__delattr__',
     '__dict__',
     '__dir__',
     '__doc__',
     '__eq__',
     '__format__',
     '__ge__',
     '__getattribute__',
     '__gt__',
     '__hash__',
     '__init__',
     '__init_subclass__',
     '__le__',
     '__lt__',
     '__module__',
     '__ne__',
     '__new__',
     '__reduce__',
     '__reduce_ex__',
     '__repr__',
     '__setattr__',
     '__sizeof__',
     '__str__',
     '__subclasshook__',
     '__weakref__',
     'print_args']
    """
    
    demo_str = "demo_str"
    dir(demo_str)
    """
    ['__add__',
     '__class__',
     '__contains__',
     '__delattr__',
     '__dir__',
     '__doc__',
     '__eq__',
     '__format__',
     '__ge__',
     '__getattribute__',
     '__getitem__',
     '__getnewargs__',
     '__gt__',
     '__hash__',
     '__init__',
     '__init_subclass__',
     '__iter__',
     '__le__',
     '__len__',
     '__lt__',
     '__mod__',
     '__mul__',
     '__ne__',
     '__new__',
     '__reduce__',
     '__reduce_ex__',
     '__repr__',
     '__rmod__',
     '__rmul__',
     '__setattr__',
     '__sizeof__',
     '__str__',
     '__subclasshook__',
     'capitalize',
     'casefold',
     'center',
     'count',
     'encode',
     'endswith',
     'expandtabs',
     'find',
     'format',
     'format_map',
     'index',
     'isalnum',
     'isalpha',
     'isascii',
     'isdecimal',
     'isdigit',
     'isidentifier',
     'islower',
     'isnumeric',
     'isprintable',
     'isspace',
     'istitle',
     'isupper',
     'join',
     'ljust',
     'lower',
     'lstrip',
     'maketrans',
     'partition',
     'replace',
     'rfind',
     'rindex',
     'rjust',
     'rpartition',
     'rsplit',
     'rstrip',
     'split',
     'splitlines',
     'startswith',
     'strip',
     'swapcase',
     'title',
     'translate',
     'upper',
     'zfill']
    """
    

    操作属性

    获取属性

    getattr()

    getattr(data, "_Data__arg1") # 1
    

    设置属性

    setattr()

    setattr(data, "name", "ok")
    print(data.name) # ok
    

    判断是否有属性

    hasattr()

    hasattr(data, "_Data__arg1") # True
    

    实例属性和类属性

    实例属性

    class Data:
        def __init__(self):
            self.name = "name"
    data = Data()
    print(data.name) # name
    

    限制实例能添加的属性

    class Data:
        __slots__ = ("name", "age") # 用元组定义允许添加的属性名称
    
    data = Data()
    data.name = "name" # 不报错
    data.num = "num" # AttributeError: 'Data' object has no attribute 'num'
    
    class Data2(Data):
        pass
    
    data2 = Data2()
    data2.num = "num" # 不报错
    

    __slots__ 仅对当前类有效,对子类无效。

    类属性

    class Data:
        name = "name"
        def __init(self):
            pass
    data = Data()
    print(data.name) # name
    

    实例方法

    给单个实例绑定方法

    class Data:
        def __init__(self):
            pass
    
    from types import MethodType
    
    def get_name(self): # 注意这里要加 self
        return "name"
    data = Data()
    data.get_name = MethodType(get_name, data)
    print(data.get_name()) # name
    data2 = Data()
    print(data2.get_name()) # AttributeError: 'Data' object has no attribute 'get_name'
    

    这个方法仅对当前示例有效。

    给所有实例绑定方法

    class Data:
        def __init__(self):
            pass
    
    def get_name(self): # 注意这里要加 self
        return "name"
    
    Data.get_name = get_name
    
    data = Data()
    print(data.get_name()) # name
    data2 = Data()
    print(data2.get_name()) # name
    

    将方法当作属性使用

    class Data:
        def __init__(self):
            pass
        @property
        def num(self):
            if not hasattr(self, "_num"):
                self._num = "None" # 这里注意不要写成 self.num,否则会死循环
            return self._num
        @num.setter
        def num(self, new_num):
            self._num = new_num
    data = Data()
    print(data.num) # None
    data.num = "new_num"
    print(data.num) # new_num
    

    子类拓展父类

    class Father(object):
        def get_args(self, *args):
            father_args = ["father arg1", "father arg2"]
            father_args += args
            return father_args
    
    
    class Son(Father):
        def get_args(self, *args):
            return super(Son, self).get_args(*args)
    
    son = Son()
    son_args = ["son arg1", "son arg2"]
    demo = son.get_args(*son_args)
    print(demo)
    
    # out
    ['father arg1', 'father arg2', 'son arg1', 'son arg2']
    

    Python 2 和 3 中 super() 的区别

    class A:
         def add(self, x):
             y = x+1
             print(y)
    class B(A):
        def add(self, x):
            super().add(x)
    b = B()
    b.add(2)  # 3
    
    #!/usr/bin/python
    # -*- coding: UTF-8 -*-
     
    class A(object):   # Python2.x 记得继承 object
        def add(self, x):
             y = x+1
             print(y)
    class B(A):
        def add(self, x):
            super(B, self).add(x)
    b = B()
    b.add(2)  # 3
    

    定制类

    类中定义了 __len__() 方法,就可以用 len()

    class Data:
        def __init__(self):
            pass
        def __len__(self):
            return 100
    data = Data()
    print(len(data)) # 100
    

    类中定义了 __str__() 方法,就可以用 str()

    class Data:
        def __init__(self):
            pass
        def __str__(self):
            return f"I'm Data"
        __repr__ = __str__ # print() 调用 __str__,ipython 交互解释器里直接输出调用 __repr__,这里让他俩输出一样
    data = Data()
    print(str(data)) # I'm Data
    

    类中定义了 __iter__() 方法,就可以被迭代`。

    class Data:
        def __init__(self):
            self.num = 0
        def __iter__(self):
            return self
        def __next__(self):
            self.num += 1
            if self.num > 10:
                raise StopIteration()
            return self.num
    
    for num in Data():
        print(num)
    """
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    """
    

    类中实现了 __getitem__() 方法,可以按照下标取值。

    class Data:
        def __getitem__(self, n): # n 可以是下标也可以是切片
            nums = [1, 2, 3, 4, 5, 6]
            if isinstance(n, int):
                for index, value in enumerate(nums):
                    if index == n:
                        return value
            elif isinstance(n, slice):
                start = n.start
                stop = n.stop
                return nums[n.start:n.stop]
    data = Data()
    print(data[3]) # 4
    print(data[2:4]) # [3, 4]
    

    类中实现了 __getattr__ 可以动态设置属性,以下是一个将链式调用转为路径的例子。

    class Data:
        def __init__(self, path=""):
            self._path = path
        def __getattr__(self, path):
            return Data(f"{self._path}/{path}")
        def __str__(self):
            return self._path
        __repr__ = __str__
    print(Data().user.name.age.nums) # /user/name/age/nums
    

    类中实现了 __call__,他的实例就可以直接在后面加 () 调用。

    class Data:
        def __call__(self):
            print("calling")
    data = Data()
    data()
    

    判断变量是否可调用

    callable(data) # True
    

    枚举类

    如果要枚举出十二生肖,除了直接定义常量,更好的方法是用枚举类:

    from enum import Enum
    
    Zodiac = Enum(
        "Zodiac",
        (
            "rat",
            "cattle",
            "tiger",
            "rabbit",
            "dragon",
            "snack",
            "horse",
            "sheep",
            "monkey",
            "chicken",
            "dog",
            "pig"
        )
    )
    
    for name, member in Zodiac.__members__.items():
        print(
            f"name:{name}\tmember:{member}\tindex:{member.value}" # member.value 是自动加上的,默认从1开始
        )
    
    """
    name:rat        member:Zodiac.rat       index:1
    name:cattle     member:Zodiac.cattle    index:2
    name:tiger      member:Zodiac.tiger     index:3
    name:rabbit     member:Zodiac.rabbit    index:4
    name:dragon     member:Zodiac.dragon    index:5
    name:snack      member:Zodiac.snack     index:6
    name:horse      member:Zodiac.horse     index:7
    name:sheep      member:Zodiac.sheep     index:8
    name:monkey     member:Zodiac.monkey    index:9
    name:chicken    member:Zodiac.chicken   index:10
    name:dog        member:Zodiac.dog       index:11
    name:pig        member:Zodiac.pig       index:12
    """
    

    自定义枚举类

    from enum import Enum, unique
    
    @unique # 保证没有重复值
    class Zodiac(Enum):
        rat = 1
        cattle = 2
        tiger = 3
        rabbit = 4
        dragon = 5
        snack = 6
        horse = 7
        sheep = 8
        monkey = 9
        chicken = 10
        dog = 11
        pig = 12
    
    zod = 1
    print(zod == Zodiac.rat.value) # True
    

    (本文完)

  • 相关阅读:
    jflex词法分析器学习笔记
    解决双系统耳机无声音的问题
    win7 x64驱动开发经验(三)windbg 双机调试配置 、问题及解决办法
    addr和offset
    MFC命令更新机制
    win7 64位驱动开发 经验(1)
    透明位图的显示 作者:王骏
    CString ,string, char* 的转换及综合比较
    SPS编辑页面布局的一个小问题
    哈希表的建立、查找。
  • 原文地址:https://www.cnblogs.com/junsircoding/p/15664982.html
Copyright © 2011-2022 走看看