面向对象的绑定方法

初始化函数

  • 指定对象的值:

class Student:
  pass

#指定属性
stu1 = Student()
stu1.name = '张无忌'
stu1.sex = 'man'
stu1.age = 18
#指定属性
stu2 = Student()
stu2.name = '周芷若'
stu2.sex = 'woman'
stu2.age = 18
  • 但是,如果有1000个学生,怎么优化写法?

定义函数,用于为对象设置属性:

def set_attr(obj,name,sex,age):
obj.name = name
obj.sex = sex
obj.age = age

set_attr(stu3,'赵敏','woman',18)
print(stu3.__dict__)
#输出内容 : {'name': '赵敏', 'sex': 'woman', 'age': 18}

 

把函数放到类中就是一个初始化函数
  • 初始化函数应该和类是一个整体

  • set_attr() 这个函数的目的用于设置对象的属性,如果没有对象此函数则没有存在的意义

新的调用方式:

class Student:
  def set_attr(obj, name, sex, age):
      obj.name = name
      obj.sex = sex
      obj.age = age
```

#新的调用方式
stu3 = Student()
Student.set_attr(stu3,'赵敏','woman',18)
print(stu3.__dict__)
  • 但是,对象与初始化函数是分开的,可以创建对象,而不必执行函数

通常对象一旦被创建,初始化函数就会执行,对象与初始化函数通常是绑定关系:

示范1:

class Student:
  #初始化函数名称是固定的,__开头__结尾的函数,会在某些时机下自动触发执行
  def __init__(self):
      print('执行了__init__')
      print(self)
      pass

s1 = Student()
#__init__在类的调用是就会执行
print(s1)
#self就是自身的意思

示范2:

class Student:
  def __init__(self):
      self.name = '张三丰'
      self.age = 78
s1 = Student()
print(s1.__dict__)
s2 = Student()
print(s2.__dict__)
#这样写死了,因为两个的值是一样的
正确的写法:
class Student:
def __init__(self,name,age):
self.name = name 
self.age = age#固定的写法,self可以自定义,但是不建议,相当于标识符

s1 = Student('张三丰',78)
print(s1.__dict__)
s2 = Student('金庸',68)
print(s2.__dict__)
总结:
  • init函数用于初始化对象,它在创建对象时,就会自动执行:

  • 并传入调用类时传递的参数,self作为第一个参数没有意义,固定写法,标识符

 

练习:

class Phone:
  def __init__(self,p_type,price,country):
      self.p_type = p_type
      self.p_price = price
      self.country = country

p1 = Phone('iphone','5800','American')
print(p1.__dict__)

 

绑定方法

  • 绑定方法有类的绑定,对象的绑定,

  • 绑定方法可以理解为绑定函数,有绑定类的方法,绑定对象的方法,以及非绑定方法

  • 在面向对象编程思想中,就是要求我们模仿现实生活中的抽象概念,因此把函数称之为方法

  • 为什么要绑定?

  • 调用函数,即处理与函数绑定在那个在一起的数据,即会返回对象

  • 而对象本质上就是一种存放数据的容器

  • 所以就相当于把数据和函数绑定在一起

  • 为什么要把数据和函数绑定在一起?

  • 得到对象,就得到了数据和处理数据的方法,就相当于执行了我们一个希望运行到的功能完整的函数.

我们实现一个循序渐进的过程:

处理一份数据:

name = '张三'
age = 20
sex = 'man'

def show_info():
  print('hello,i am %s my age is %s my sex %s'%(name,age,sex))
show_info()

把数据引用到一个函数里面,完成对其的调用或处理

如果继续重复这样的数据,我们需要重新定义变量的值,可以优化为传参的形式:


def show_info(name,age,sex):
  print('hello,i am %s my age is %s my sex %s'%(name,age,sex))
show_info(name,age,sex)
name = '张三'
age = 20
sex = 'man'

 

但是,传参的缺点如下:

  • 传参的缺点在于如果参数的传递形式或者格式有误,报错

  • 另一方面如果传入的参数较多,费时费力,解决办法的一种方式是把数据装到容器里

  • 但是每次处理都要需要先获取数据,然后再传递给函数,依然比较容易出错

  • 而且数据和函数是分离的,所以

  • ** 将要处理的数据与处理数据的函数进行绑定,函数和数据就不是分离状态了**

  • 如何绑定,就得用类和对象了

代码:

绑定对象
class Student:
  school = 'BeiJing'

  def __init__(self,name,sex,age):
      self.name = name
      self.sex = sex
      self.age = age

  赋予某些技能(方法)
  def learning(self):
      print('正在学习...')

  赋予某些具体的技能
  def say_hi(self):
      print('hello,i am %s my age is %s my sex %s'%(self.name,self.age,self.sex) )
  默认情况下,在类中定义的方法都是绑定方法
   
stu1 = Student('李白',18,'man')
stu1.say_hi()#用对象调用
Student.say_hi(stu1)#用类调用

注释:以对象开头,用对象来调类中的方法(函数),默认会把对象传入方法中,也就是self,自身的意思

以类开头,用类来调用方法时,需要手动传入对象

 

内存原理(可以无视):

  • print(stu1.say_hi)

    输出 : <bound method Student.say_hi of <main.Student object at 0x000001CE452B9EF0>>

    这是一个绑定方法,本质上是Student类中的sayhi函数,现在把这个函数绑定给内存中地址为0x000001CE452B9EF0的对象

  • 只要拿到对象,就同时拿到了数据和处理数据的方法,这就是之所以绑定的原因

  • 可以更有效和更有效率的处理数据
  • 以上是绑定给对象的方法,默认是绑定对象的
  • 绑定给对象的意思就是方法(函数)用的都是类里面对象的内容,而不直接调用类
绑定类:
class Student:
  school = 'BeiJing'#school就是类里的属性
  def __init__(self,name,sex,age):
      self.name = name#这些就是对象的属性
      self.sex = sex
      self.age = age
       
  (self.age_1 = age)也可以这样写,age_1是可变的,不过默认两边是一样的
   
  这是绑定给对象的方法,只涉及对象
  def sayhello(self):
      print(self.name,'你好')
       
       
  绑定给类的方法,直接访问类,需要一个装饰器,默认参数变为cls,类的缩写,固定格式
  @classmethod
  def print_school(cls):         
      print('学校名为%s'%Student.school)#访问类中叫school的属性
      print(cls.school)    
       
  def sayhello(self):
      print(self.school) # 这样也可以操作,但是要用对象去掉,违背初衷,且太过于麻烦

Student.print_school()#类的调用

s1 = Student('name','sex','age')
s1.sayhello()#对象的调用

解释:

  • 不加装饰器,正常调用不需要传入参数,就像访问普通函数一样,

  • 但是函数需要一个参数,这是类中方法的固定用法,因此不可避免要报错。

  • 引入@classmethod装饰器,固定用法,cls表示类,缩写

     

      • 明确两点

      如何定义对象绑定方法,以及类的绑定方法:

      绑定对象是用于调取对象(非类里)属性的方法,绑定类是调取类的属性

      在调用时有何区别

      绑定类要加@classmethod装饰器

      • 思考,一个方法在什么场景下会绑定对象或者类?

        当要处理的数据包含在类里时,就不能绑定给对象,应该直接绑定给类

        当要处理的数据包含在对象里时,就应该直接绑定给对象

非绑定方法
class Teacher:
  def __init__(self,name,sex):
      self.name = name
      self.sex = sex

  @staticmethod #静态方法,用于定义一个非绑定方法
  def test_func():       #也可以传参
      print('test_func, run!')
Teacher.test_func()         #类访问
t1 = Teacher('name','fun')
t1.test_func()             #对象访问

非绑定方法,在类中定义,既不绑定给类,也不绑定给对象 特点: 没有自动传参的效果,谁都可以调用,就是一个普通函数 使用场景,这个功能不需要访问类和对象的数据

 

练习

1.创建Student类

2.拥有以下属性: 姓名 性别 年龄 学校 班级

3.拥有以下方法

  • save(name) 其作用是将这个对象序列化到文件中

  • get_obj(name) 其作用是根据name从文件中反序列化为得到一个对象

  • 分析save方法和get_obj 应该作为绑定给对象还是绑定给类

import json

class Student:

  school = "beijing"

  def __init__(self,name,sex,age,classes):
      self.name = name
      self.age = age
      self.sex = sex
      self.classes = classes


  def save(self):
      dic = {"name":self.name,"sex":self.sex,
              "age":self.age,"classes":self.classes}
      with open(self.name,"wt",encoding="utf-8") as f:
          json.dump(dic,f)

  @classmethod
  def get_obj(cls,name):
      with open(name,"rt",encoding="utf-8") as f:
          dic = json.load(f)
      obj = cls(dic["name"],dic["sex"],dic["age"],dic["classes"])
      return obj




# stu1 = Student("阿尔法","man",20,"py5期")
# stu2 = Student("张三","woman",20,"py5期")


# stu1.save()
# stu2.save()

stu = Student.get_obj("阿尔法")
print(stu)
print(stu.name)

 

总结

类和对象的绑定方法的总结

1,相同点 都会自动传值 都可以被类和对象调用 参数名都可以被修改,但是不建议修改 2,不同点 对象绑定方法在对象调用时,传的是对象自己,而类绑定方法自动传的是类自己 第一个参数不一样,一个是self , 一个是cls

 

 

 

 

个人总结

访问顺序:

对象 ------> 类

调用方式:

1,对象调用

以对象开头的调用方式,对象要先定义对象,因此要用对象传参

2,类的调用

以类的名字开头的调用方式,不用提前定义

初始化函数:

以init为标志的函数,通常直接与方法绑定,方法直接调用其内定义的属性

绑定方法:

1,对象的绑定

对象的绑定就是方法中,参数是初始化函数定义中的属性,函数的结果或返回值就是对象

2,类的绑定

类的绑定就是方法中,直接调用初始化函数之外的属性,要加一个装饰器@classmethod

绑定的情景:

1,对象的绑定

属性在对象里,就不需要绑定给类,多此一举

2,类的绑定

属性包含在类里,直接绑定给类

非绑定方法:

在类中定义,既不绑定给类,也不绑定给对象

 

已解决

类的公共内容是什么?

是类里所有对象共有的属性,也即是初始化函数之外的内容,一般写在初始化函数上面

对象跟类是什么关系?

对象是使用类里某些属性和方法的东西,实例化的内容,从类里创建出来的内容

调用类会产生对象,返回的是对象

初始化函数外的属性是不是叫类里的属性?

不止是之外的属性,类里的所有东西都是一种属性,方法也是一种属性,万物皆对象,万物皆属性

方法是函数,也是对象的技能,也是一种属性.

怎么区分处理的数据是在对象里还是类里?

区分对象属性和类里属性 : 共有的是类的属性,传参的是对象的属性.

对象里是作为属性返回的,类是是共有的属性

对象的属性和技能?

属性是类似于你的名字,身高,体重,年龄,技能就类似于你使用的python

对象的属性和技能就是调用类里属性和方法返回的值.

 

猜你喜欢

转载自www.cnblogs.com/wang-kai-1994/p/10167172.html
今日推荐