4月16日 python学习总结 封装之property、多态 、classmethod和staticmethod
阅读原文时间:2023年07月09日阅读:1

一、封装之property

@property把一个函数伪装成一个数据类型

   @伪装成数据的函数名.setter   控制该数据的修改,修改该数据时触发

   @伪装成数据的函数名.delect  控制该数据的删除,删除该数据时触发

class People:
def __init__(self,name):
self.__name=name

@property                  #将name()函数伪装成一个数据属性name  
def name(self): #obj.name  
    print('您现在访问的是用户名。。。')  
    return self.\_\_name

@name.setter #obj.name='EGON'      执行 name=x 修改 name 值时触发该方法  
def name(self,x):  
    # print('=================',x)  
    if type(x) is not str:  
        raise TypeError('名字必须是str类型,傻叉')  
    self.\_\_name=x

@name.deleter         # 执行 del 对象.name 时触发该方法  
def name(self):  
    # print('就不让你删')  
    del self.\_\_name

obj=People('egon')

print(obj.name)

print(obj.name())

print(obj.name)

obj.name='EGON'

print(obj.name)

obj.name=123

del obj.name
obj.name

二、多态

1、 什么是多态
      多态指的是同一种事物多种形态

2、为什要用多态
用基类创建一套统一的规则,强制子类去遵循(使用抽象类实现),这样便可以
在不用考虑对象具体类型的前提下而直接使用对象下的方法

3、多态性:一种调用方式,不同的执行效果(多态性)

    注意:多态与多态性是两种概念

4、多态的使用

  • * 继承 

    class Animal:  
        def eat(self):  
            pass  
        def bark(self):  
             print('叫')
    
    class Cat(Animal):  
        def jiao(self):  
            print('喵喵喵')
    
    class Dog(Animal):  
        def speak(self):  
            print('汪汪汪')
    
    class Pig(Animal):  
        def han(self):  
            print('哼哼哼')
    
    c=Cat()  
    d=Dog()  
    p=Pig()
    
    # 多态性:可以在不用考虑对象具体类型的前提下而直接使用对象下的方法  
    # c.eat()  
    # d.eat()  
    # p.eat()
    
    # d.bark()  
    # p.bark()  
    # c.bark()
    
    d.speak()  
    c.jiao()  
    p.han()
    • 抽象类

      import abc #abstract class
      class Animal(metaclass=abc.ABCMeta):
      @abc.abstractmethod
      def eat(self):
      pass

      @abc.abstractmethod  
      def bark(self):  
          pass

      obj=Animal() # 抽象基类本身不能被实例化

      class Cat(Animal):
      def eat(self):
      print('cat eat')

      def bark(self):  
          print('喵喵喵')

      class Dog(Animal):
      def eat(self):
      print('dog eat')

      def bark(self):  
          print('汪汪汪')

      class Pig(Animal):
      def eat(self):
      print('pig eat')
      def bark(self):
      print('哼哼哼')

      c=Cat()
      d=Dog()
      p=Pig()

      c.bark()

      d.bark()

      p.bark()

      def BARK(Animal): 向上转型

      Animal.bark()

      BARK(c)

      BARK(d)

      BARK(p)

    • 鸭子类型(长得像鸭子就被当作是鸭子)

      class Foo:
      def f1(self):
      print('from foo.f1')

      def f2(self):  
          print('from foo.f2')

      class Bar:
      def f1(self):
      print('from bar.f1')

      def f2(self):  
          print('from bar.f2')

      obj1=Foo()
      obj2=Bar()

      obj1.f1()
      obj1.f2()

      obj2.f1()
      obj2.f2()

      class Disk:
      def read(self):
      print('disk read')

      def write(self):  
          print('disk write')

      class Txt:
      def read(self):
      print('txt read')

      def write(self):  
          print('txt write')

      class Process:
      def read(self):
      print('process read')

      def write(self):  
          print('process write')

      obj1=Disk()
      obj2=Txt()
      obj3=Process()

      obj1.read()
      obj2.read()
      obj3.read()

三、classmethod和staticmethod****

classmethod

   绑定方法:

     在类内部定义的函数,默认就是给对象来用,而且是绑定给对象用的,称为对象的绑定方法

      1.  绑定对象的方法特殊之处:

应该由对象来调用,对象来调用,会自动将对象当作第一个参数传入

2.  绑定到类的方法特殊之处:

应该由类来调用,类来调用,会自动将类当作第一个参数传入

import settings

class People:
def __init__(self,name,age):
self.name=name
self.age=age

def tell(self):  
    print('%s:%s' %(self.name,self.age))

@classmethod  
def from\_conf(cls):  
    return cls(settings.NAME,settings.AGE)

p=People('egon',19)

p.tell()

p1=People(settings.NAME,settings.AGE)

p1.tell()

p2=People(settings.Name,settings.AGE)

p3=People('alex',74)

p3.tell()

print(People.from_conf)

p4=People.from_conf(People)

print(People.from_conf)

p4=People.from_conf()

p4.tell()

2、staticmethod:

非绑定方法,就是一个普通函数

特性: 既不跟类绑定,也不跟对象绑定,这意味着谁都能用

谁来用都是一个普通函数,也就是说没有自动传值的特性了

import settings
import hashlib
import time

class People:
def __init__(self,name,age):
self.uid=self.create_id()
self.name=name
self.age=age

def tell(self):  
    print('%s: %s:%s' %(self.uid,self.name,self.age))

@classmethod  
def from\_conf(cls):  
    return cls(settings.NAME,settings.AGE)

@staticmethod  
def create\_id():  
    m=hashlib.md5()  
    m.update(str(time.clock()).encode('utf-8'))  
    return m.hexdigest()

obj=People('egon',18)

print(obj.uid,obj.name,obj.age)

obj.tell()

print(obj.create_id)

print(People.create_id)

print(obj.create_id())
print(People.create_id())

作业、

'''
4月16
'''
'''
1、定义MySQL类(参考答案:http://www.cnblogs.com/linhaifeng/articles/7341177.html#_label5)
  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方法用来从文件中反序列化出对象
'''
import hashlib
import time
import pickle
import os
from days22 import setting

class MySQL:
def __init__(self, host, port):
self.__host = host
self.__port = port
self.__id = self.create_id()

@staticmethod  
def create\_id():  
    m = hashlib.md5()  
    m.update(str(time.clock()).encode('utf-8'))  
    return m.hexdigest()

@classmethod  
def creae\_mysql(cla):  
    return cla(setting.HOST, setting.PORT)

def save(self):  
    path = os.path.join(setting.DB\_PATH, '%s.pk' % self.\_\_id)  
    if os.path.exists(path):  
        raise ImportError('该id已存在')  
    else:  
        with open(path, 'wb')as f:  
            pickle.dump(self, f)

def get\_obj\_by\_id(self):  
    path = os.path.join(setting.DB\_PATH, '%s.pk' % self.\_\_id)  
    if not os.path.exists(path):  
        raise ImportError('该id不存在')  
        # print('该id不存在')  
    else:  
        with open(path, 'rb')as f:  
            return pickle.load(f)

m1 = MySQL('h1', 'p1')

m2 = MySQL.creae_mysql()

m2.save()

print(m2.get_obj_by_id().__dict__)

# m1.save()

m1.get_obj_by_id()

'''
2、定义一个类:圆形,该类有半径,周长,面积等属性,将半径隐藏起来,将周长与面积开放
参考答案(http://www.cnblogs.com/linhaifeng/articles/7340801.html#_label4)
'''
class Circle:
def __init__(self,radius):
self.__radius=radius
@property
def perimeter(self):
return 2*(3.14)*self.__radius
@property
def area(self):
return (3.14)*(self.__radius**2)

c1=Circle(3)

print(c1.area)

print(c1.perimeter)

'''
3、明日默写
1、简述面向对象三大特性:继承、封装、多态
继承:继承是一种新建类的方式,新建类称之为子类或派生类,父类称之为基类或者超类,子类会‘遗传’父类的属性
封装:装就是把一对属性装起来,封就是把这些属性藏起来
封装对外隐藏,对内开放
多态:一种事物的多种形态;多态主要体现在继承、抽象类抽象方法、鸭子类型
多态性:调用同方一方法,有不同的执行效果
2、定义一个人的类,人有名字,身高,体重,用property讲体质参数封装成人的数据属性
class People:
def __init__(self,name,hight,weight):
self.__name=name
self.__hight=hight
self.__weight=weight
@property
def bmi(self):
return self.__weight/(self.__hight**2)
3、简述什么是绑定方法与非绑定方法,他们各自的特点是什么?
绑定方法:在类内部定义的函数,默认就是给对象来用,而且是绑定给对象用的,称为对象的绑定方法
若该函数是绑定给类用的,称之为类的绑定方法
非绑定方法:既不跟类绑定,也不跟对象绑定,这意味着谁都能用
谁来用都是一个普通函数,也就是说没有自动传值的特性了
'''