Python笔记(4):面向对象,迭代器,生产器

Python 构造函数:

class FooBar:
    def __init__(self):
        self.somevar = 42
运行结果
>>> f = FooBar()
>>> f.somevar
42

接受参数的构造函数:

class FooBar:
    def __init__(self, value=42):
        self.somevar = value
结果:
>>> f = FooBar('This is a constructor argument')
>>> f.somevar

析构函数

__del__

由于Python有carbage colletion的机制,所以,建议尽量不要使用析构函数

调用超类super的构造函数

由于在子类中,超类的构造函数被重载,所以超类构造函数里面定义的变量,在子类中都不会声明,要避免这种情况,需要在子类的构造函数中调用超类的构造函数,这里有两种方法。
第一种,直接利用超类名来构造。
class SongBird(Bird):
    def __init__(self):
        Bird.__init__(self)
        self.sound = 'Squawk!'
    def sing(self):
        print self.sound

第二种方法,利用super函数。
__metaclass__ = type # super only works with new-style classes
class Bird:
    def __init__(self):
        self.hungry = True
    def eat(self):
        if self.hungry:
        print 'Aaaah...'
        self.hungry = False
        else:
        print 'No, thanks!'
class SongBird(Bird):
    def __init__(self):
        super(SongBird, self).__init__()
        self.sound = 'Squawk!'

        def sing(self):
                print self.sound

最好使用super函数的方法,这有很多好处,特别是在有多个超类的时候。

Basic Sequence and Mapping protocol

Sequence 和 Mapping是最基本的数据的集合。要实现他们的行为,如果是immutable的需要完成两个protocol,如果是mutable的话需要完成4个protocol

__len__(self): 用来返回集合中的元素个数,如果是Sequence的话,返回值则是Sequence里面的元素的个数,如果是Mapping的话,返回的值是key-value对的数目。如果__len__返回0,那么在需要布尔值的情况会转换为false。.
__getitem__(self, key): 用来返回key所对应的值。入股是Sequence,这个key就是一个小于元素个数的整数。如果是mapping那么就可以是任意一个值。

__setitem__(self, key, value): 将value存储在key所对应的位置。
__delitem__(self, key): 当使用del语句时,用来删除key对对应的元素。

exstra:

在一个Sequence中如果这个整数是一个负数,那么则相当与从底端开始x[-n] 相当与x[len(x)-n]

当键值不匹配的时候抛出一个TypeError异常

当索引的类型正确,但是越界了,则抛出一个IndexError

下面是一个无穷数列的代码:

def checkIndex(key):
    """
    Is the given key an acceptable index?
    To be acceptable, the key should be a non-negative integer. If it
    is not an integer, a TypeError is raised; if it is negative, an
    IndexError is raised (since the sequence is of infinite length).
    """
    if not isinstance(key, (int, long)): raise TypeError
    if key<0: raise IndexError
class ArithmeticSequence:
   def __init__(self, start=0, step=1):
      """
      Initialize the arithmetic sequence.
      start - the first value in the sequence
      step - the difference between two adjacent values
      changed - a dictionary of values that have been modified by
      the user
      """
      self.start = start
      # Store the start value
      self.step = step
      # Store the step value
      self.changed = {}
      # No items have been modified
   def __getitem__(self, key):
      """
      Get an item from the arithmetic sequence.
      """
      checkIndex(key)
      try: return self.changed[key]           # Modified?
      except KeyError:                             # otherwise...
         return self.start + key*self.step    # ...calculate the value


    def __setitem__(self, key, value):
        """
        Change an item in the arithmetic sequence.
        """
        checkIndex(key)
        self.changed[key] = value             # Store the changed value
结果:

>>> s = ArithmeticSequence(1, 2)
>>>s[4]
9
>>>s[4] = 2

>>>s[4]
2
>>>s[5]
11


类中的属性,用访问器(accessor)来访问的话,可以通过property函数来使得他与普通的属性访问方法相同,比如:
__metaclass__ = type
class Rectangle:
    def __init__(self):
        self.width = 0
        self.height = 0
    def setSize(self, size):
        self.width, self.height = size
    def getSize(self):
        return self.width, self.height
    size = property(getSize, setSize)

运行结果:

>>> r = Rectangle()
>>> r.width = 10
>>> r.height = 5
>>> r.size
(10, 5)
>>> r.size = 150, 100
>>> r.width
150

访问起来,类似于C++中重载了 =操作符,一点要注意的是property函数第一个参数是getter,第二个是setter,还有这是new style的class。

property可以接受,0个,1个,2个,3个和四个参数,四个参数分别为fget, fset, fdel, doc,如果是0个参数,那么就不可读也不可写,如果是1个参数,那么是只读;两个参数是可读可写,三个参数是可以删除,第四个是document。

静态方法(static method)和类方法(class method)

静态方法和类方法可以直接通过类来访问,静态方法不需要参数,类方法需要一个类似与self的参数cls。定义的方法如下:
__metaclass__ = type
class MyClass:
        def smeth():
            print 'This is a static method'
            smeth = staticmethod(smeth)
        def cmeth(cls):
            print 'This is a class method of', cls
            cmeth = classmethod(cmeth)

2.4以后的版本,提供了一种新的定义方法,如下:
__metaclass__ = type
class MyClass:
    @staticmethod
    def smeth():
        print 'This is a static method'
    @classmethod
    def cmeth(cls):
        print 'This is a class method of', cls

运行的结果如下:

>>> MyClass.smeth()
This is a static method
>>> MyClass.cmeth()
This is a class method of <class '__main__.MyClass'>

由于一些历史原因python静态方法和类方法用的不是很多,但是现在在一些特殊场合,比如工厂方法的时候,经常使用。


 迭代器(iterator)

除了List和dict以外,其他的对象也能迭代,只要实现了__iter__这个magic 方法,__iter__不不接收参数,返回一个任意实现了next方法对象的迭代器。next()函数用来返回迭代器的“下一个值“,如果下一个值不返回任何的东西的话,需要抛出一个StopIteration的异常。

在python3.0中迭代器协议发生了改变, 迭代的对象需要实现__next__函数,而不是next,next()是一个新的内嵌函数比如next(it)等价与之前版本的it.next().

下面是一个无穷队列Fibolacci数列:

class Fibs:
    def __init__(self):
        self.a = 0
        self.b = 1
    def next(self):
        self.a, self.b = self.b, self.a+self.b
        return self.a
    def __iter__(self):
        return self

内嵌的iter函数,可以将可迭代的对象转化为迭代器

>>> it = iter([1, 2, 3])
>>> it.next()
1
>>> it.next()
2

也可以从迭代器来生成一个序列:

lass TestIterator:

    value = 0
    def next(self):
        self.value += 1
        if self.value > 10: raise StopIteration
        return self.value
    def __iter__(self):
        return self
运行结果:

>>> ti = TestIterator()
>>> list(ti)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]


生产器(generator)

生产器是一种特殊的迭代器,它的定义类似于函数的定义,可以看看如下的例子,下面的代码是一个生产器,把一个多维数组平滑输出,既将一个数组的数组里面的数据按顺序输出成一列
nested = [[1, 2], [3, 4], [5]]

def flatten(nested):
    for sublist in nested:
        for element in sublist:
            yield element

你可以这样使用生产器
>>> nested = [[1, 2], [3, 4], [5]]
>>> for num in flatten(nested):
           print num

也可以这样使用

>>> list(flatten(nested))
[1, 2, 3, 4, 5]

在2.4以后的版本,提供了一种新的语法,就是生产器表达式(generator comprehension or generator expression),它类似与List conprehension,但是它不是生成一个list而是返回一个生产器,这样的话,就可以方便你一步一步的处理
>>> g = ((i+2)**2 for i in range(2,27))
>>> g.next()

16

生产器还有一个优点,就是你如果在函数调用中使用生产器,那么不需要多余的括号,如下

sum(i**2 for i in range(10))


递归生产器

上面的例子只能flatten两层的list,如果是一个多层次混合的话,就需要递归了:
def flatten(nested):
    try:
        for sublist in nested:
            for element in flatten(sublist):
                yield element
    except TypeError:
        yield nested
结果:

>>> list(flatten(['foo', ['bar', ['baz']]]))
['foo', 'bar', 'baz']


如果没有yield的话,可以模拟生产器,代码如下:
def flatten(nested):
    result = []
    try:
    # Don't iterate over string-like objects:
        try: nested + ''
        except TypeError: pass
        else: raise TypeError
        for sublist in nested:
            for element in flatten(sublist):
                result.append(element)
   except TypeError:
        result.append(nested)
    return result



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SQLAlchemy 是一个 SQL 工具包和对象关系映射(ORM)库,用于 Python 编程语言。它提供了一个高级的 SQL 工具和对象关系映射工具,允许开发者以 Python 类和对象的形式操作数据库,而无需编写大量的 SQL 语句。SQLAlchemy 建立在 DBAPI 之上,支持多种数据库后端,如 SQLite, MySQL, PostgreSQL 等。 SQLAlchemy 的核心功能: 对象关系映射(ORM): SQLAlchemy 允许开发者使用 Python 类来表示数据库表,使用类的实例表示表中的行。 开发者可以定义类之间的关系(如一对多、多对多),SQLAlchemy 会自动处理这些关系在数据库中的映射。 通过 ORM,开发者可以像操作 Python 对象一样操作数据库,这大大简化了数据库操作的复杂性。 表达式语言: SQLAlchemy 提供了一个丰富的 SQL 表达式语言,允许开发者以 Python 表达式的方式编写复杂的 SQL 查询。 表达式语言提供了对 SQL 语句的灵活控制,同时保持了代码的可读性和可维护性。 数据库引擎和连接池: SQLAlchemy 支持多种数据库后端,并且为每种后端提供了对应的数据库引擎。 它还提供了连接池管理功能,以优化数据库连接的创建、使用和释放。 会话管理: SQLAlchemy 使用会话(Session)来管理对象的持久化状态。 会话提供了一个工作单元(unit of work)和身份映射(identity map)的概念,使得对象的状态管理和查询更加高效。 事件系统: SQLAlchemy 提供了一个事件系统,允许开发者在 ORM 的各个生命周期阶段插入自定义的钩子函数。 这使得开发者可以在对象加载、修改、删除等操作时执行额外的逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值