极简Python入门

 

 本文旨在帮助从总体上帮助了解Python的一些基本属性,具体的使用技巧需要通过不断实践积累


一、Python的基本特性


二、Python的类

    面向对象编程,是一种程序设计思想。OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。

1、类

创建办法:

    class Student(object):    pass

如果没有合适继承类,使用object类,所有类都会继承的类。通过__init__方法,可以将必须绑定的属性强制写入。

    class Student(object): def __init__(self, name, score):    self.name = name    self.score = score

第一参数永远是self,创建的实例本身。

2、访问限制

    在类变量的前加入__,就会变成私有变量。内部能访问,外部不能访问。私有变量的实现其实是对变量别名。

class Student(object):    

    def __init__(self, name, score):   

        self.__name = name

        self.__score = score

python解释器对外将__name变量改成_Student__name。访问_Student__name还是可以访问__name变量。

类似:__XXX__是特殊变量,可以直接引用,但是有特殊用途,如if __name__ == '__main__':,我们自己变量一般不用这种变量名。

_XXX和__XXX这样的函数和变量“不应该”被直接引用。

3、继承与多态

从现有的class继承,新的class称为子类。被继承的class称为基类、父类、或超类。如:

class Animal(object):

      def run(self):

      print('Animal is running...')

Dog,Cat从Animal继承:

class Dog(Animal):  

    pass

class Cat(Animal): 

    pass

作用:

(1)继承类获得父类的全部功能;Dog,Cat都有run()方法,也可以增加自己的方法。

(2)可以对继承方法修改。当子类和父类都有同一方法时,调用时,子类覆盖父类的方法。提现继承的多态性,一个Dog实例化的对象,即是属于Dog类,也属于Animal类。

(3)继承可以一级一级继承下来。因此一个类可以继承多个类的特性。

4、动态语言和静态语言

      编写一个接受Animal类型的变量

      def run_twice(animal): 

             animal.run() 

             animal.run()

可以对实例后传参,run_twice(Dog())、run_twice(Cat());

    对于静态语言,如果需要传入Animal类型,则传入对象必须是Animal类或者它的子类,否则不能调用run方法。但是对于python这种动态语言而言,只需要保证传入对象有一个run()方法就可以了。

    class Timer(object):

          def run(self):

              print('Start...')

     因此也能调用run_twice函数调用run()方法。run_twice(Timer())。也就是只要一个对象“看起来像鸭子,走起路来像鸭子”,那它就可以看做鸭子。

5、获取对象信息

(1)type():判断对象类型;

(2)isinstance():判断class的类型,判断一个对象是否属于某个类。能用type判断的类型也能用isinstance()判断。

(3)dir():获取一个对象的所有属性和方法。

(4)之前说的__xxx__有特殊作用,比如__len__方法,我们调用len()函数获取对象长度时,len()函数内部会自动调用__len__()方法。

因此,计算len('ABC')等价'ABC'.__len__()

(5)利用getattr()、setattr、hasattr可以直接操作对象的状态。

hasattr():判断是否有某个属性;

getattr():获取属性值

setattr():设置一个属性值。


三、Python高级属性

1、__slots__

定义一个class,创建实例后,我们可以给实例绑定任何属性和方法。由于动态语言的灵活性。

class Student(object):

    pass

实例化,s = Student()

s.name = 'Michiael'

或绑定方法

def set_age(self,age):

    self.age  = age

from types  import MethodType

s.set_age = MethodType(set_age,s)

但是给一个实例绑定的方法,在另一个实例中不起作用。

如果需要限制实例的属性,只允许name和age属性。可以用__slots__变量限制。

class Student(object):

    __slots__ = ('name','age')

__slots__定义属性只对当前实例起作用,对于继承的子类不起作用。

2、@property

在绑定属性时,属性的值可以随便改动,无法检查参数。如 s.score = 9999,需要限制score范围,因此可以设置set_score()和get_score()获取成绩

class Student(object):

      def get_score(self):

          return self._score

      def set_score(self, value):

           if not isinstance(value, int):

                raise ValueError('score must be an integer!')

           if value < 0 or value > 100:

                raise ValueError('score must between 0 ~ 100!')

          self._score = value

s = Student()后,s.set_score(60)是正常的,s.set_score(9999)会报错。

    但是这种限制方法,调用比较复杂,是否能实现s.score = 9999这样简单的访问变量,又能检查参数,python的@property能够实现,它是将一个方法变成属性调用。

class Student(object):

    @property

    def score(self):

          return self._score

    @score.setter

    def score(self, value):

          if not isinstance(value, int):

                raise ValueError('score must be an integer!')

           if value < 0 or value > 100:

                raise ValueError('score must between 0 ~ 100!')

           self._score = value

上面将getter方法变成了属性值,@property又创建一个装饰器@score.setter将setter方法变成属性赋值。

3、多重继承

      一个子类可以继承多个父类,通过多重继承,一个子类就可以同时获得多个父类的所有功能。

      通常类的继承关系。都是主线单一继承下来的。这样在继承多个类时,会导致复杂而庞大的继承链。如果需要混入额外的功能,可以进行同时继承多个类,这种设计成为Mixin。

如:

class Dog(Mammal,RunnableMinxIN,  \

  CarnivorousMixin):

    pass

4、定制类

      Pythonc的class中有许多特殊用途的函数,可帮助定制类。

(1)__str__:显示字符

(2)__iter__:需要设置一个类,像for ...in循环访问,类似list或tuple,需要实现__iter__方法。

(3)__getitem__:虽然实现__iter__能够作用for循环,但是还是不能像list那样取元素,如果想像list按照下标取出元素,需要实现__getitem__方法。

def __getitem__(self, n):

    a, b = 1, 1

    for x in range(n):

        a, b = b, a + b

    return a

(4)__getattr__:python调用不存在的属性时,一般程序会报错,如果加入__getattr__,Python试图调用,来获取属性。

(5)__call__:调用实例方法时,是通过instance.method()调用,通过__call__可实现在实例本身调用。或者说,将类对象当做函数使用。如:

class DistanceForm(object):

    def __init__(self, origin):

        self.origin = origin

        print "origin :"+str(origin)

    def __call__(self, x):

        print "x :"+str(x)

    p = DistanceForm(100)

    p(2000) #类似函数方式,直接赋值调用。

python还有很多定制方法。可查官网。

5、使用元类

    type()函数既可以返回一个对象的类型,也可以创建一个新的类型。比如可以用type创建一个类。

    Hello = type('Hello', (object,), dict(hello=fn))

创建的参数:

(1)class的名称;

(2)继承的父类集合,注意Python支持多重继承,如果只有一个父类,别忘了tuple的单元素写法;

(3)class的方法名称与函数绑定,这里我们把函数fn绑定到方法名hello上。除了通过type()动态创建类外,还可以是使用mataclass。元类是类的类。一个实例创建的完整过程应该是,先创建一个元类,元类创建类,类创建实例。

    type函数实际就是一个元类,也是Python背后创建所有类的元类。

我们可以自定义元类:

# metaclass是类的模板,所以必须从`type`类型派生:

class ListMetaclass(type):

    def __new__(cls, name, bases, attrs):

        attrs['add'] = lambda self, value: self.append(value)

        return type.__new__(cls, name, bases, attrs)

class MyList(list, metaclass=ListMetaclass):    pass

Mylist创建时,是通过ListMetaclass.__new__创建。因此可以修改类的定义,或加入新方法。

__new__()方法接收到的参数依次是:

1、当前准备创建的类的对象;

2、类的名字;

3、类继承的父类集合;

4、类的方法集合。

实例化:

L = MyList()   此时可以实现 add调用。L.add(1)


四、Python小实践

    实现模式向kindle中推送任意数量本地书籍:

# sendmail.py

from email.mime.text import MIMEText

from email.mime.multipart import MIMEMultipart

import smtplib

from os.path import basename

from_addr = "xxxxxx@126.com"

password = "######"

to_addr = "xxxxxx@kindle.cn"

smtp_server = "smtp.126.com"

def send_mail(attachments=None):

   msg = MIMEMultipart()

   msg['Subject'] = "SendingBook"

   msg['From'] = from_addr

   msg['To'] = to_addr

   msg['Accept-Language'] = 'zh-CN,utf-8'

   msg['Accept-Charset'] = 'ISO-8859-1,utf-8'  

   attachments = [ "D:/电子书/kindle/"+x for x in attachments] 

   for attachment in attachments or []:

      files=attachment

      file_name = basename(attachment)

      attr = MIMEText(open('%s'%files,'rb').read(),'base64','utf-8')

      attr["Content-Type"] = 'application/octet-stream'

      attr["Content-Disposition"] = 'attachment;filename="%s"'%file_name

      msg.attach(attr)

   server = smtplib.SMTP(smtp_server)

   server.starttls()

   server.login(from_addr,password)

   server.sendmail(from_addr,to_addr,msg.as_string())

   server.quit()

if __name__=='__main__':

  import sys

  if len(sys.argv) > 1:

     attachment = sys.argv[1:]

  else:

     attachment = []

  send_mail(attachment) 

调用方法:python sendmail.py Python-web-spider.mobi ,目前调用时,存在一个问题,书籍名中不支持中文。

参考地址:http://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000


免责声明:本文系网络转载。版权归原作者所有。如涉及版权,请联系删除!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值