Python攻克之路-类的成员

1、类的成员之字段
描述:创建一个类,类里可以定义一个方法,在init里还有self.什么,self.什么,这叫做成员,在类里可以写什么,类中的方法与对象并没联系

class Foo:
#代码从是到下执行创建了一个Foo类,Foo类里有一个init函数,还有一个show方法,当代码到show为止,都没有执行,因为没有调用,
 相当于show方法整体保存在类里,如果创建一个对象时,这个对象会自动执行init方法,init方法写了self.name = name,self代指
 的是当前的方法,name里保存传的值name='reid',它是保存在对象中
    def __init__(self, name):
        self.name = name  #self代指是对象,是保存在对象中,实际这种叫做字段,调用字段不用括号()
    def show(self):       #方法
        print(self.name)
obj = Foo('reid')
obj.name     #字段直接可以调用 
obj.show()   #方法要加括号才可以调用

  

(1).字段分类
  普通字段:self.what = what 保存在对象,只能通过对象访问
  静态字段:保存在类中,执行可以通过对象访问,也可以通过类访问,只保留一份,如果被修改就是显示修改后的值
  场景:列出中国所有省份,用面向对象的知识表示?
分析:要创建一个省份的类

class Province:
    country = 'china'  #静态字段,属于类,与对象无关,代码从上到下执行,当执行到self.name=name,静态字段就被创建了
    def __init__(self, name,country='china'):
        self.name = name    
        #普通字段,属于对象,当p1 = Province('hainan')执行一次,这行代码就会被执行
        #self.country = country  
p1 = Province('hainan')   #省份中要保存一个值,它是中国的,也就是说每个省份都是中国的,每个省都保存了一份
p2 = Province('fujian')
Province.country   #它属于类,可以直接调用,但是不能通过类找对象如Province.name是找不到的
p1.name  使用对象访问
p1.country   #对象也可以访问静态字段


2.类的成员之方法
方法:show整体保存在类
  - 普通方法:保存在类中,由对象来调用,self是调用者对象
  - 静态方法:保存在类中,由类直接调用
  - 类方法: 保丰在类中,由类直接调用,cls是当前类
应用场景:
分析:对于普通方法要建立对象,才能访问它,所以对象也要内存
a.如果对象中需要保存一些值,调用方法时需要利用对象中的值时,就用普通方法,因为对象中是封装值的
b.如果要执行某个功能而不依赖其他的值,直接可以调用这个功能,要直接创建这个对象,这个对象是空的,通过对象调用,对象已经创建,但是里面什么值也没有,使用静态方法,与类方法差别不大,有个参数问题,如果在方法中会使用到当前类,不想自己写,使用类方法会帮忙传入,但是没有太大的功能
(1).普通

In [1]: class Foo:
   ...:     def bar(self):
   ...:         print('bar')
   ...: obj = Foo()
   ...: obj.bar()       #通过对象访问方法,对象通过类对象指针找到这个方法,通过类也可以直接找到,推荐使用
   ...: 
bar
In [2]: obj=Foo()
In [3]: Foo.bar(obj)   #通过类来调用
bar

(2).静态

In [4]: class Foo:  
   ...:     def bar(self):
   ...:         print('bar')
   ...:     @staticmethod      #装饰器,表示静态方法
   ...:     def sta():         #传入的参数self不是必需的,不用创建对象,直接使用类就可以调用
   ...:         print('static')
   ...: Foo.sta()
   ...: 
static
传参:
In [6]: class Foo:
   ...:     def bar(self):
   ...:         print('bar')
   ...:     @staticmethod
   ...:     def sta(a1,a2):
   ...:         print(a1,a2)
   ...: Foo.sta(2,3)
2 3

(3).类方法

In [3]: class Foo:
   ...:     def bar(self):        #self是对象
   ...:         print('bar')
   ...:     @classmethod
   ...:     def classmd(cls):    #一定要有一个参数,不写self,要写成cls,它是类名,不依赖于对象
   ...:         print('classmd')
   ...: Foo.classmd()  #并没传参数,但是有个cls是Python自动传入的参数,传入类名Foo
   ...: 
<class '__main__.Foo'>  主程序中的Foo类
classmd

  

3.成员属性:有方法的影子,也有字段的特性
注:访问时,字段不加括号,对于方法是加括号

In [2]: class Foo:
   ...:     def __init__(self):   #字段,obj.name
   ...:         self.name = 'a'
   ...:     def bar(self):        #方法
   ...:         print('bar')
   ...:     def per(self):
   ...:         print('per')
   ...: obj = Foo()
   ...: obj.per()
per

In [3]: class Foo:
   ...:     def __init__(self):
   ...:         self.name = 'a'
   ...:     def bar(self):
   ...:         print('bar')
   ...:     @property         #加上装饰器后,不使用括号来调用
   ...:     def per(self):    #定义时像方法,调用时像字段
   ...:         print('per')
   ...: obj = Foo()
   ...: obj.per
per

In [4]: class Foo:
   ...:     def __init__(self):
   ...:         self.name = 'a'
   ...:     def bar(self):
   ...:         print('bar')
   ...:     @property
   ...:     def per(self):
   ...:         print('per')
   ...:         return 1       #有返回值
   ...: obj = Foo()
   ...: r = obj.per
   ...: print(r)
per
1

(1).成员属性的赋值
描述:需要赋值就要有一个方法帮助接收,所以需要创建一个方法,希望赋值时,执行这个方法

In [9]: class Foo:
   ...:     def __init__(self):
   ...:         self.name = 'a'
   ...:     def bar(self):
   ...:         print('bar')
   ...:     @property            #用于执行obj.per
   ...:     def per(self):       #当执行r = obj.per时,会执行这个方法
   ...:         print('per')
   ...:         return 1
   ...:     @per.setter          #通过per来执行
   ...:     def per(self,val):   #新建一个方法,当obj.per = 123时,执行这个方法
   ...:         print(val)
   ...: obj = Foo()
   ...: r = obj.per
   ...: print(r)
   ...: obj.per = 123  #重新赋值,无论是写,还是调用都是通过对象.per来执行
   ...: 
   ...: 
per
1
123

(2).删除的实现
分析:再定义一个方法来执行,函数时,定义一个函数名,函数名加个括号就可以执行,函数内的操作是自定义,这是python中规定的语法,这里写了一个类中的方法使用装饰器装饰了,通过对象点什么执行时,自动就会执行这个方法

[root@node2 class]# cat cls.py 
#!/usr/local/python3/bin/python3
class Foo:
    def __init__(self):
        self.name = 'a'
    def bar(self):
        print('bar')
    @property
    def per(self):
        print('per')
        return 1
    @per.setter
    def per(self,val):
        print(val)
    @per.deleter        ##目的是伪造和字段一样,这种操作不会真实的去获取数据
    def per(self):      
        print('del')
obj = Foo()
r = obj.per
print(r)
obj.per = 123
del obj.per
[root@node2 class]# python3 cls.py 
per
1
123
del

(3).示例:利用属性实现分页

[root@node2 class]# cat page_show.py 
#!/usr/local/python3/bin/python3
li = []
for i in range(100):
    li.append(i)
print(li[0:10])
[root@node2 class]# python3 page_show.py  #如当输入1时,显示10条
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

编写起始和结尾页

[root@node2 class]# cat page_show.py 
#!/usr/local/python3/bin/python3
li = []
for i in range(100):
    li.append(i)
p = input('input the page: ')  #1,show 10
p = int(p)
# 1, 0 to 10
# 2, 10 to 20
start = (p-1) * 10  #当p=1时,1-1=0,再乘以10,还是0
end = p * 10        #p=1时,1*10=10,也就是当输入1时,是1到10
print(li[0:10])

[root@node2 class]# cat page_show.py 
#!/usr/local/python3/bin/python3
li = []
for i in range(100):
    li.append(i)

while True:
    p = input('input the page: ')  #1,show 10
    p = int(p)
    # 1, 0 to 10
    # 2, 10 to 20
    start = (p-1) * 10
    end = p * 10
    print(li[start:end])
[root@node2 class]# python3 page_show.py 
input the page: 1
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
input the page: 2
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19]

把start,end单独写成一个组件
分析:一般是放在终端上查看的,如果放在web框架会要做更多的操作,还要生成html的页码,所以要把它专门放到一个组件中完成,只需要调用它,它告诉结果就可以了,可以专门写一个类来实现

[root@node2 class]# cat page_show.py 
#!/usr/local/python3/bin/python3
class Pagecon:
    def __init__(self,current_page):
        self.page = int(current_page)
    def start(self):                  #使用两个方法来计算开始和结束的
        val = (self.page-1) * 10
        return val

    def end(self):
        val = self.page * 10
        return val
li = []
for i in range(100):
    li.append(i)

while True:
    p = input('input the page: ')  #1,show 10
    obj = Pagecon(p)
    # 1, 0 to 10
    # 2, 10 to 20
    print(li[obj.start():obj.end()]) 

异常处理:当用户输入不是数字时,要做判断和处理

[root@node2 class]# cat page_show.py 
#!/usr/local/python3/bin/python3
class Pagecon:
    def __init__(self,current_page):
        try:                            #异常处理
            p = int(current_page)       #如果是传入1,就转换成数字1
        except Exception as e:          #如果传入是sdfljdsf,不是数字的,就会执行excetpion
            p = 1                       #如果输入不会法,让它的默认值就是1
        self.page = p                   #
 
    def start(self):
        val = (self.page-1) * 10
        return val

    def end(self):
        val = self.page * 10
        return val
li = []
for i in range(100):
    li.append(i)

while True:
    p = input('input the page: ')  #1,show 10
    obj = Pagecon(p)
    # 1, 0 to 10
    # 2, 10 to 20
    print(li[obj.start():obj.end()])   #方法的调用

属性处理时,可以更好的整理,不会太乱

[root@node2 class]# cat page_show.py 
#!/usr/local/python3/bin/python3
class Pagecon:
    def __init__(self,current_page):
        try:
            p = int(current_page)
        except Exception as e:
            p = 1
        self.page = p

    @property                      #######
    def start(self):
        val = (self.page-1) * 10
        return val

    @property                      #######
    def end(self):
        val = self.page * 10
        return val
li = []
for i in range(100):
    li.append(i)

while True:
    p = input('input the page: ')  #1,show 10
    obj = Pagecon(p)
    # 1, 0 to 10
    # 2, 10 to 20
    print(li[obj.start:obj.end])        #调用时不用带括号 

测试:
[root@node2 class]# python3 page_show.py 
input the page: 1
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
input the page: 3
[20, 21, 22, 23, 24, 25, 26, 27, 28, 29]
input the page: sdlk
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

  

4.属性的另一种写法

[root@node2 class]# cat pro.py 
#!/usr/local/python3/bin/python3
class Foo:
    def f1(self):
        return 123
    per = property(fget=f1)
obj = Foo()
ret = obj.per  #当执行这行代码时,fget=f1,所以自动执行def f1返回123
print(ret)
[root@node2 class]# python3 pro.py 
123

相同的写法

    @property
    def per(self):
        return 123

设置多个参数

[root@node2 class]# cat pro.py 
#!/usr/local/python3/bin/python3
class Foo:
    def f1(self):
        return 123
 
    def f2(self,v):       #v来接收多一个参数
        print(v)      
    per = property(fget=f1,fset=f2)

obj = Foo()
#ret = obj.per
#print(ret)
obj.per = 123456          #赋值
[root@node2 class]# python3 pro.py 
123456

[root@node2 class]# cat pro.py 
#!/usr/local/python3/bin/python3
class Foo:
    def f1(self):
        return 123

    def f2(self,v):
        print(v)

    def f3(self):
        print('del')
    per = property(fget=f1,fset=f2,fdel=f3)   ####最多三个值,最大三个函数,还有一个参数,doc=是注释

obj = Foo()
#ret = obj.per
#print(ret)
#obj.per = 123456
del obj.per                                   ####
[root@node2 class]# python3 pro.py 
del

对应关系

 

posted @ 2018-05-02 12:39  Reid21  阅读(153)  评论(0编辑  收藏  举报