zoukankan      html  css  js  c++  java
  • python学习笔记(2)

    面向对象编程

    python可以直接使用class进行类的创建和使用

    class Animal():
        def __init__(self, name):
            self.name = name
        def print_name():
            print(self.name)
        def print_type():
            print("animal")
    
    a = Animali("lili")
    a.print_name()    # lili
    a.print_type()    # animal

    a就是类Animal的实例化对象,可以使用类定义的一些属性,但是此时我们可以在外部进行使用和操作a的name

    a.name = "xiaoxiao"
    print(a.name)    # xiaoxiao

    在大部分情况,我们可能不希望对象的私有属性能随意的被外部修改和操作,如果在属性前面加上__就默认为私有变量,只能在对象内部函数能够操作

    class Animal():
        def __init__(self, name):
            self.__name = name
        def print_name(self):
            print(self.__name)
        def print_type(self):
            print("animal")
    
    a = Animali("lili")
    a.print_name()    # lili
    a.print_type()    # animal
    
    print(a.__name)    # 'Animal' object has no attribute '__name'

    而对于共有属性来说,我们可以通过getattr和hasattr来进行获取属性的值或者判断对象是否存在该属性,而不至于出现上述的报错情况

    print(getattr(a, "__name"), "not fount")    # not fount
    print(getattr(a, "print_name", "not fount"))    # <bound method print_name of <__main__.Count object at 0x0000011FAFC86550>>
    
    print(hasattr(a, "__name"))    # False
    print(haseattr(a, "print_name"))    # True

    当然,还有一种属性叫做类属性,属于类而不是属于实例化对象,所有的对象都可以访问,类也可以直接访问

    class Animal():
        count = 0    #    添加计数器,每次实例化增加1
        def __init(self, name):
            self.__name = name
            Animal.count += 1
        def print_name(self):
            print(self.__name)
    
    print(Animal.count)    # 0
    a = Animal("xiaoxiao")
    print(Animal.count)    # 1
    print(a.count)    # 1

    同样的,我们也可以给实例化对象添加自己额外的属性

    a.weight = 10
    print(a.weight)    # 10
    print(Animal.weight)    # type object 'Count' has no attribute 'hehe'

    也可以添加私有的方法

    # MethodType可以绑定self
    from types import MethodType
    
    def set_name(self, name):
        self.name = name
    
    # 绑定自定义的函数
    a.set_name = MethodType(set_name, a)
    
    a.set_name("xiao bai")
    
    print(a.name)    # xiao bai

    当然,我们可能不会希望使用者能随意的添加属性到实例化对象,我们可以通过slots来进行限制

    class Animal(object):
        __slots__ = ("name", "weight")
        def __init__(self, name):
            self.name = name
    
    a = Animal("xixi")
    a.age = 1
    print(a.age)    # 'Animal' object has no attribute '_Animal__age'

     class也提供了对应的getter和setter操作来监听属性的变化,当然可能比起vue来说相对难看一点

    class Animal(object):
        def __init__(self, name):
            self.__name = name
        
        @property
        def name(self):
            print("get")
            return def.__name
    
        @name.setter
        def name(self, name):
            print("set")
            self.__name = name
    
    a = Animal("xiao bai")
    
    a.name = "da bai"    # set
    
    print(a.name)    # get    # da bai

    但是,如果我们只写getter那一部分的话,则会得到can't set attribute的提示,说明属性是只读属性

    我们可以看到,通过打印实例化对象,会返回一段地址,看起来肥肠的难受,class里面支持修改__str__以及__repr__来个性化打印信息

    class Animal(object):
        def __init__(self, name):
            self.name = name
        def __str__(self):
            return "name: " + self.name
        __repr__ = __str__
    
    a = Animal("xiao bai")
    
    print(a)    # name: xiaobai

     同时,class也可以支持迭代器,只需要实现__iter__和__next__方法,然后不停返回下一个迭代就好,也可以实现__getitem__方法来实现下标访问

    class Fib(object):
        def __init__(self):
            self.a, self.b = 0, 1
    
        def __iter__(self):
            return self
        
        def __next__(self):
            self.a, self.b = self.b, self.a + self.b
            if self.a > 100000:
                raise StopIteration()
            return self.a
    
    f = fib()
    for i in Fib():
        print(i)    #0, 1, 1, 2, 3, 5 ......75025
    
    class Myarr(object):
        def __getitem__(self, index):
            a, b = 1, 1
          for x in range(n):
              a, b = b, a + b
          return a
    
    print(Myarr[1])    # 1

    但是,如果传入的是切片的话,就会有问题了,print(Myarr()[1: 5]),所以,还需要在getitem里面处理一下

    class Myarr(object):
        def __getitem__(self, n):
            if isinstance(n, int): # n是索引
                a, b = 1, 1
                for x in range(n):
                    a, b = b, a + b
                return a
            if isinstance(n, slice): # n是切片
                start = n.start
                stop = n.stop
                if start is None:
                    start = 0
                a, b = 1, 1
                L = []
                for x in range(stop):
                    if x >= start:
                        L.append(a)
                    a, b = b, a + b
                return L
    
    print(Myarr()[1:5])    # [1,2,3,5]

     一个链式调用的demo,可以用来定制api

    class Chain(object):
    
        def __init__(self, path=''):
            self._path = path
    
        def __getattr__(self, path):
            return Chain('%s/%s' % (self._path, path))
    
        def __str__(self):
            return self._path
    
        __repr__ = __str__
    
    Chain().status.user.timeline.list    # '/status/user/timeline/list'
    Chain().users('michael').repos    # '/users/:user/repos'

    python同时也提供了可以调用实例化对象的方法,可以将对象当做方法来调用,可以通过callable来判断一个对象或者方法能否被调用

    class Animal(object):
         def __init__(self, name):
            self.name = name
    
        def __call__(self):
            print("my name is %s" % self.name)
    
    a = Animal("xiao bai")
    
    a()    # my name is xiao bai
    
    callable(a)    # True
  • 相关阅读:
    SQL Server 调优系列进阶篇
    封装 RabbitMQ.NET
    RabbitMQ 的行为艺术
    SQL Server 调优系列进阶篇
    SQL Server 调优系列进阶篇
    FastFrameWork 快速开发框架
    SQL Server 调优系列进阶篇
    Java基础:三目运算符
    marquee标签,好神奇啊...
    Java JFrame 和 Frame 的区别
  • 原文地址:https://www.cnblogs.com/timmer/p/10097757.html
Copyright © 2011-2022 走看看