Python心经(5)

目录

python对于类和实例,,都能随时动态绑定 属性或者函数 

可以通过__slots__去限定实例所能绑定属性的范围

python里面类很多定制函数__xx__

下面给个python里面枚举类型

对type函数去实现

有关迭代器:

生成器:

 可迭代对象:

有关python继承你需要了解

python对于类和实例,,都能随时动态绑定 属性或者函数 

print('ABC'.lower())

class TT(object):
    pass

def func(self,arg):
    self.arg=arg
    print(self.arg)
#python这个动态语言允许,在运行时给类或者实例去绑定新的属性/函数
#对这个类绑定了func,就相当于在TT类里面实现了一个func函数
#这是其他静态语言所不允许的
TT.func=func
TT.func(TT(),5)
t=TT()
t.func(6)

Python心经(5)_第1张图片

注意属性并不是一定需要的,,可有可无,只是稍微简单了一下代码 

可以通过__slots__去限定实例所能绑定属性的范围

但是对于类本身来说没什么区别,,想添加属性也是可以的

#如果想对实例的属性做限制 可以用__slots__
class Student(object):
    __slots__ = ('name', 'age') # 用tuple定义允许绑定的属性名称

#实例一个Student对象
s=Student()
s.socre=50 #不可以,,类做了限制,,实例绑定属性只能绑定name和age
s.age=0
s.name='sad'

Student.socre=10 #但是对于类本身来说没什么区别,,想添加属性也是可以的
print(Student.socre)
print(Student.age)

注意 __slots__定义的属性仅对当前类实例起作用,对继承的子类是不起作用的:

class boy(Student):
    pass
bo=boy()
bo.socre=50
print(bo.socre)

这样是ok的, 想要再限制,那就在子类做__slots__限制

对于python来说私有 就是在前面加__两个杠去表示,属性啊,方法,变量等等都可以用

继承的话,子类没法继承父类的私有的东西,就没法直接使用

对于 非要想在外部去使用私有的东西,方法如下:_xx.__私有 ,不建议 

Python心经(5)_第2张图片

如果想要对函数参数做检查,一般写起来函数内部比较麻烦,需要搞个set,get方法,,使用@property装饰器,可以把方法变为属性调用

把一个getter方法变成属性,只需要加上@property就可以了,此时,@property本身又创建了另一个装饰器@score.setter,负责把一个setter方法变成属性赋值,于是,我们就拥有一个可控的属性操作:

class Student(object):
    
    @property
    def socre(self):
        return self._socre
    
    @socre.setter
    def socre(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._socre = value

s=Student()
s.socre=60  #方法当作属性去调用了 s.set_socre(60)
print(s.socre) #其实就是s.get_socre()
class Student(object):

    @property
    def birth(self):
        return self._birth

    @birth.setter
    def birth(self, value):
        self._birth = value

    @property
    def age(self):
        return 2015 - self._birth

s=Student()
s.birth=15
print(s.age)

Python内置有三大装饰器:@staticmethod(静态方法)、@classmethod(类方法)、@property(描述符),其中静态方法就是定义在类里的函数,并没有非要定义的必要;类方法则是在调用类属性、传递类对象时使用;而@property则是一个非常好用的语法糖。@property最大的好处就是在类中把一个方法变成属性调用,起到既能检查属性,还能用属性的方式来访问该属性的作用。

可以通过装饰器去访问到类的私有成员

@property应用
  让我们先看下@property的应用,其功能1是可定义只读属性,也就是真正意义上的私有属性(属性前双下划线的私有属性也是可以访问的,具体参照这篇文章:私有属性真的是私有的吗?)。实例需求是定义类Person,具有年龄和姓名,要求年龄必须等于18,则代码如下:

class Person(object):
    def __init__(self, name, age=18):
        self.name = name
        self.__age = 18

    @property
    def age(self):
        return self.__age
        
xm = Person('xiaoming')  #定义一个人名小明
print(xm.age)    #结果为18
xm.age = -4    #报错无法给年龄赋值
print(xm.age)



  在python中定义只读属性非@property莫属,如果细心留意大部分源码,都跑不了@property的身影。而定义只读属性也很简单:以需要定义的属性为方法名(上例age属性定义为方法),其上装饰内置装饰器@property就ok了。
  @property真正强大的是可以限制属性的定义。往往我们定义类,希望其中的属性必须符合实际,但因为在__init__里定义的属性可以随意的修改,导致很难实现。如我想实现Person类,规定每个人(即创建的实例)的年龄必须大于18岁,正常实现的话,则必须将属性age设为只读属性,然后通过方法来赋值,代码如下:

class Person(object):
    def __init__(self, name, age):
        self.name = name
        self.__age = 18

    @property
    def age(self):
        return self.__age

    def set_age(self, age): #定义函数来给self.__age赋值
        if age < 18:
            print('年龄必须大于18岁')
            return
        self.__age = age
        return self.__age
     
     xm = Person('xiaoming', 20)
     
print(xm.age)
print('----------')
xm.set_age(10)
print(xm.age)
print('----------')
xm.set_age(20)
print(xm.age)


  可以看到,通过方法的确能限制输入,但是不是每个人都记得方法名,有什么简化的方法呢?@property就能很轻松办到,修改代码如下:

class Person(object):
    def __init__(self, name, age):
        self.name = name
        self.__age = 18

    @property
    def age(self):
        return self.__age

    @age.setter
    def age(self, age):
        if age < 18:
            print('年龄必须大于18岁')
            return
        self.__age = age
        return self.__age

xm = Person('xiaoming', 20)
print(xm.age)
print('----------')
xm.age = 10
print(xm.age)
print('----------')
xm.age = 20
print(xm.age)

  结果和上图一致。两段代码变化的内容:将set_age修改为age,并且在上方加入装饰器@age.setter。这就是@property定义可访问属性的语法,即仍旧以属性名为方法名,并在方法名上增加@属性.setter就行了。
 

python里面类很多定制函数__xx__ 

这里不说了

Python心经(5)_第3张图片

Python心经(5)_第4张图片

向打开文件的with方法,内部就是封装了相对的__enter__和__exit__ 

下面给个python里面枚举类型

下面是用enum函数去创建枚举类,也可以自己写类去继承Enum,去实现一个枚举类

from enum import Enum

Month = Enum('Month', ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'))
for name, member in Month.__members__.items():
    print(name, '=>', member, ',', member.value)

type()函数既可以返回一个对象的类型,又可以创建出新的类型,比如,我们可以通过type()函数创建出Hello类,而无需通过class Hello(object)...的定义:

对于这个类:

class Hello(object):
    def hello(self, name='world'):
        print('Hello, %s.' % name)
  

对type函数去实现

def fn(self, name='world'): # 先定义函数
     print('Hello, %s.' % name)


Hello = type('Hello', (object,), dict(hello=fn)) # 创建Hello class
h = Hello()
h.hello()

print(type(Hello))
print(type(h))

要创建一个class对象,type()函数依次传入3个参数:

  1. class的名称;
  2. 继承的父类集合,注意Python支持多重继承,如果只有一个父类,别忘了tuple的单元素写法;
  3. class的方法名称与函数绑定,这里我们把函数fn绑定到方法名hello上。

通过type()函数创建的类和直接写class是完全一样的,因为Python解释器遇到class定义时,仅仅是扫描一下class定义的语法,然后调用type()函数创建出class。

有关迭代器:

Python心经(5)_第5张图片

生成器:

Python心经(5)_第6张图片

 可迭代对象:

执行__iter__返回了迭代器对象或者生成器对象,之后就进到迭代器或者生成器,,然后自动调__next__,这样就是达到了for循环。 python的for循环 或者range或者常见的数据类型比如list,元组,字典等等 对象其实都是返回可迭代对象,都是可以迭代的。

Python心经(5)_第7张图片

Python心经(5)_第8张图片

有关python继承你需要了解

Python心经(5)_第9张图片

 但是对于复杂的继承关系,我们可以通过mro方法去获得这个类的继承关系

Python心经(5)_第10张图片

 Python心经(5)_第11张图片

你可能感兴趣的:(Python,python,开发语言)