面向对象之绑定方法与非绑定方法

一、类中函数的分类

  类中定义的函数分为两大类,分别是绑定方法和非绑定方法。

 

二、绑定方法

  1、定义:绑定给谁,谁来调用就自动将它本身当作第一个参数传入。

  2、绑定到类的方法:用classmethod装饰器装饰的方法,是一种为类量身定制的方法。

    使用方法:类名.boud_method(),自动将类当作第一个参数传入(对象也可调用,但类仍被当作第一个参数自动传入)

    如:  

#!/usr/bin/env python3
#-*- coding:utf-8 -*-

class Func:
    def __init__(self,name):
        self.name = name

    @classmethod  # 绑定到类的方法,一般由类调用
    def func1(cls):
        print(cls,"类调用")
Func.func1() #输出: <class '__main__.Func'> 类调用

obj = Func.func1() # 实例化对象
obj.func1() # 对象也可调用,但是默认传的参数仍然是类

  3、绑定到对象的方法:没有被任何装饰器修施的方法,为对象量身定制。

    使用方法:对象.boud_method() ,自动将对象当作第一个参数传入

    如:

#!/usr/bin/env python3
#-*- coding:utf-8 -*-

class Func:
    def __init__(self,name):
        self.name = name

    def tell(self) # 绑定到对象的方法,仅由对象来调用
    print("姓名是:%s,由对象%f调用"%self.name)
func = Func('cc') # 实例化一个对象
func.tell() # 输出:姓名是cc,由对象调用
# Func.tell() # 类调用时报错,故绑定到对象的方法只能由对象来调用

 

三、非绑定方法

  1、定义:不与类或对象绑定,类和对象都可以调用,但是没有自动传值一说,简言之,非绑定方法就是一个普通工具。

    注意:要与绑定到对象方法区分开,在类中直接定义的函数,没有被任何装饰器修饰的,就是绑定到对象的方法,不是普通函数,能够自动传值;而staticmethod装饰的方法,任谁调用,都没有自动传值。

  2、使用方法:对象/类.method(),全部参数都需要手动传入

    如:

#!/usr/bin/env python3
#-*- coding:utf-8 -*-

class Func:
    def __init__(self):
        self.name = name

    @staticmethod # 非绑定方法,类和对象均可带调用,无自动传值
    def func2(a,b):
        print('类或对象均可',a+b)

func.func2(5,6) # 输出:11 类与对象均可
Func.func2(4,7) # 输出:11 类与对象均可

 

四、classmethod 和 staticmethod 的对比

# settings.py

name = 'cc'
age = 21
male = 'male'
DB_PATH = 'D:\pycharm\Test1\Thrid_module\面向对象编程
# test.py
import settings

import settings
class Introduce:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    @staticmethod
    def intro_yourself():
        return Introduce(settings.name,settings.age)

    @classmethod # 哪个类来调用,就将那个类当作第一个参数传入
    def tell_others(cls):
        return cls(settings.name,settings.age)

    def __str__(self):
        return 'Your power is not enough!'

class Test(Introduce):
        def __str__(self):
            return '<%s,%s>'%(self.name,self,age)

per1 = Test.intro_yourself() 
print(per1) # 输出:Your power is not enough! # 原本想触发Test.__str__执行,但结果是触发了Introduce.__str__的执行。

per2 = Test.tell_others()
print(per2) # 输出: <cc,21>

 

五、三种方法的综合使用

class People:
    def __init__(self,name,age,sex):
        self.id = self.set_id()
        self.name = name
        self.age = age
        self.sex = sex
    def tell_info(self): # 绑定到对象的方法
        print('姓名:%s' '年龄:%s' '性别:%s'%(self.name, self.age, self.sex))

    @classmethod  # 绑定到类的方法
    def from_class(cls):
        obj = cls(
            settings.name,
            settings.age,
            settings.sex
        )
        return obj

    @staticmethod  # 静态方法,非绑定方法
    def set_id():
        m = hashlib.md5(str(time.time()).encode('utf-8'))
        return m.hexdigest()

#p = People('sc',20,'male')
# 绑定到对象,就应该由对象来调用,自动将对象本身当作第一个参数传入
#p.tell_info() #姓名:sc年龄:20性别:male

# 绑定给类,就应该由类来调用,自动将类本身当作第一个参数传入
#p = People.from_class() # 等同于People.from_class(People)
#print(p.tell_info()) # 姓名:cc年龄:21性别:male

# 非绑定方法,不与类或对象绑定,谁都可以调用,没有自动传值一说
p1 = People('sc1',20,'male')
p2 = People('SC2',21,'MALE')
p3 = People('Sc3',22,'Male')

 

六、绑定方法与非绑定方法的练习

  要求:      

1.对象有id、host、port三个属性

2.定义工具create_id,在实例化时为每个对象随机生成id,保证id唯一

3.提供两种实例化方式,方式一:用户传入host和port 方式二:从配置文件中读取host和port进行实例化

4.为对象定制方法,save和get_obj_by_id,save能自动将对象序列化到文件中,文件路径为配置文件中DB_PATH,文件名为id号,保存之前验证对象是否已经存在,若存在则抛出异常,;get_obj_by_id方法用来从文件中反序列化出对象。

 

#settings.py
HOST = '127.0.0.1'
PORT = 3302
DB_PATH = 'D:\pycharm\Test1\Thrid_module\面向对象编程\Test\db'

# test.py
import settings
import  hashlib
import time
import os
import pickle

class Mysql:
    def __init__(self,host,port):
        self.id = self.creat_id()
        self.host = host
        self.port = port
    @staticmethod
    def creat_id():
        m = hashlib.md5(str(time.time()).encode('utf-8'))
        return m.hexdigest()

    def save(self):
        '''自动将对象序列化到文件中,路径为DB_PATH,文件名为id号'''
        try:
             if not isinstance(self,str):
                 with open(os.path.join(settings.DB_PATH,self.id),'wb') as f:
                     pickle.dump(self,f)
        except Exception as e:
            print('error',e)

    def get_obj_by_id(self):
        try:
            if os.path.isfile(os.path.join(settings.DB_PATH,self.id)):
                with open(os.path.join(settings.DB_PATH,self.id),'rb') as f:
                    data =  pickle.load(self,f)
                    return data
        except Exception as e:
            print('error',e)

    def bound1(self):
        return Mysql(self.host,self.port)

    @classmethod
    def bound2(cls):
        return cls(settings.Host,settings.PORT)


obj1 = Mysql('127.0.0.1',6666)
print(obj1)
obj2 = Mysql.creat_id()
print(obj2)
View Code

 

posted @ 2018-03-24 17:09  暮光微凉  阅读(262)  评论(0编辑  收藏  举报