zoukankan      html  css  js  c++  java
  • Python自动化开发课堂笔记【Day07】

    类与对象

    对象是特征(变量)与技能(函数)的结合体,类是一系列对象共有的特征与技能的结合体
      现实生活中:先有对象,再总结归纳出类
      程序中:一定是先定义类,再实例化出对象
    定义类的语法:
    class 类名:
      '''注释'''
      类体(可以是任意代码)

    1 class Chinese:
    2     country = 'China'
    3     def __init__(self,name,age):
    4         self.name = name
    5         self.age = age
    6         print('--->',self.name,self.age)
    7     def talk(self):
    8         print('say Chinese')

    1. 类的第一种用法,实例化

    1 p1 = Chinese('Albert',18)
    2 p2 = Chinese('Baker',33)

    2. 类的第二种用法,属性引用

    1 print(Chinese.country)#类的数据属性
    2 print(Chinese.__init__)#类的函数属性
    3 p1.__init__('Talbert',81)

      3. 其他知识点补充

     1 print(Chinese.__dict__)#查看类的属性字典,或者说是名称空间
     2 #{'__module__': '__main__', '__doc__': None, 'talk': <function Chinese.talk at 0x00675D68>, '__weakref__': <attribute '__weakref__' of 'Chinese' objects>, 'country': 'China', '__dict__': <attribute '__dict__' of 'Chinese' objects>, '__init__': <function Chinese.__init__ at 0x00675228>}
     3 print(Chinese.country)
     4 print(Chinese.__dict__['country'])#效果同上,本质上是如何取到的country这个变量
     5 print(p1.name,p1.age)
     6 print(p1.__dict__['name'],p1.__dict__['age'])
     7 
     8 #类型和类是统一的
     9 print(type(p1)) #<class '__main__.Chinese'>
    10 
    11 #类中定义的变量对象是公用的,不会产生新的内存空间
    12 print(id(p1.country)) #5593664
    13 print(id(p2.country)) #5593664
    14 print(id(Chinese.country)) #5593664

    类绑定方法(类实例化后绑定到对象身上)
    绑定方法:绑定到谁身上就是给谁用的,谁来调用就会自动把自己当作第一个参数传入

    1 print(Chinese.talk) #<function Chinese.talk at 0x006F5D68>
    2 print(p1.talk) #<bound method Chinese.talk of <__main__.Chinese object at 0x002759F0>>
    3 print(p2.talk) #<bound method Chinese.talk of <__main__.Chinese object at 0x0070EB50>>

    总结:定义在类内部的变量是所有对象共有的,id全一样。定义在类内部的函数,是绑定到所有对象的,是给对象来用的,obj.func()会把obj本身当作第一个参数传入
      print(p1.x) # p1.__dict__ ---> Chinese.__dict__ ---> 报错
    如果要查找一个属性,先从对象名称空间中查找,找不到之后再到类名称空间查找,如果还找不到不会再去全局找,直接报错

    练习:

     1 1.统计类实例化对象的次数
     2 class Chinese:
     3     country = 'China'
     4     count = 0
     5     def __init__(self,name,age):
     6         self.name = name
     7         self.age = age
     8         Chinese.count += 1 #类变量的概念
     9         print('--->',self.name,self.age)
    10         print('%d obj create' % Chinese.count)
    11 p1=Chinese('A',1)
    12 p2=Chinese('B',2)
    13 
    14 2.定义一个学生类
    15 class Stu:
    16     def __init__(self,stuid,name,age):
    17         self.stuid = stuid
    18         self.name = name
    19         self.age = age
    20         print('Student--->',self.stuid,self.name,self.age)
    21 s1 = Stu(1,'A',18)
    22 s2 = Stu(2,'B',18)
    23 
    24 3.类对象交互
    25 class A:
    26     camp = 'AAA'
    27     def __init__(self,nickname,damage=100, HP=200):
    28         self.nickname = nickname
    29         self.damage = damage
    30         self.HP = HP
    31     def attack(self,enemy):
    32         enemy.HP -= self.damage
    33         print('造成%d点伤害' % self.damage)
    34 class B:
    35     camp = 'BBB'
    36     def __init__(self,nickname,damage=200, HP=100):
    37         self.nickname = nickname
    38         self.damage = damage
    39         self.HP = HP
    40     def attack(self,enemy):
    41         enemy.HP -= self.damage
    42         print('造成%d点伤害' % self.damage)
    43 a1 = A('a1')
    44 b1 = B('b1')
    45 print(a1.camp)
    46 print(b1.camp)
    47 a1.attack(b1)
    48 b1.attack(a1)

    继承

      继承是一种创建新类的方式,新建的类可以继承一个或多个父类,父类又可以称为基类或超类,新建的类称为派生类或子类

    1 class ParentClass1:
    2     pass
    3 class ParentClass2:
    4     pass
    5 class SubClass1(ParentClass1):
    6     pass
    7 class SubClass2(ParentClass1,ParentClass2):
    8     pass

    如何查看继承的父类

    1 print(SubClass1.__bases__) #(<class '__main__.ParentClass1'>,)
    2 print(SubClass2.__bases__) #(<class '__main__.ParentClass1'>, <class '__main__.ParentClass2'>)

      类的种类

     1 #Python2中分为新式类和经典类
     2 #新式类(有括号的,有继承关系的) 
     3 class Foo(object):
     4     pass
     5 #经典类(没括号的,谁都不继承)
     6 class Bar:
     7     pass
     8 #Python3中全部都是经典类(即使没有括号也是新式类)
     9 class Foo:
    10     pass
    11 print(Foo.__bases__) #(<class 'object'>,)

    继承的好处:
      1.减少冗余代码
      2.在子类定义新的属性,覆盖掉父类的属性,称为派生

     1 class Animal:
     2     def __init__(self,name,age,sex):
     3         self.name = name
     4         self.age = age
     5         self.sex =sex
     6     def eat(self):
     7         print('eating...')
     8     def talk(self):
     9         print('%s saying...' % self.name)
    10 class People(Animal):
    11     def __init__(self,name,age,sex,edu):
    12         Animal.__init__(self,name,age,sex)
    13         self.edu = edu
    14     def talk(self):
    15         Animal.talk(self)
    16         print('%s say hello' % self.name)
    17 class Pig(Animal):
    18     pass
    19 class Dog(Animal):
    20     pass
    21 p1 = People('p1',18,'male','college')
    22 g1 = Pig('g1',11,'female')
    23 d1 = Dog('d1',22,'male')
    24 print(p1.edu)
    25 p1.talk()
    26 g1.talk()
    27 d1.talk()
    28 print(isinstance(p1,People))
    29 print(isinstance(g1,Pig))
    30 print(isinstance(d1,Dog))

      对象如果要调用方法,先从对象自己的命名空间找,然后是自己的类,最后是父类,依次往上找

     1 class Parent:
     2     def foo(self):
     3         print('Parent.foo')
     4         self.bar()
     5     def bar(self):
     6         print('Parent.bar')
     7 class Sub(Parent):
     8     def bar(self):
     9         print('Sub.bar')
    10 s=Sub()
    11 s.foo() # Parent.foo
    12         # Sub.bar

    继承反应的是一种什么是什么的关系
    组合也可以解决代码冗余的问题,但是组合反应的是一种什么有什么的关系

     1 class People:
     2     def __init__(self,name,age,sex):
     3         self.name=name
     4         self.age=age
     5         self.sex=sex
     6 class Date:
     7     def __init__(self,y,m,d):
     8         self.y = y
     9         self.m = m
    10         self.d = d
    11     def tell(self):
    12         print('%s-%s-%s' % (self.y,self.m,self.d))
    13 class Teacher(People):
    14     def __init__(self,name,age,sex,salary,y,m,d):
    15         People.__init__(self,name,age,sex)
    16         self.salary = salary
    17         self.birth = Date(y,m,d)
    18 
    19 class Student(People):
    20     def __init__(self,name,age,sex,y,m,d):
    21         People.__init__(self,name,age,sex)
    22         self.birth = Date(y,m,d)
    23 
    24 t1 = Teacher('A',18,'male',3000,2000,1,1)
    25 t1.birth.tell()

    抽象类

     1 import abc
     2 class File(metaclass=abc.ABCMeta):
     3     @abc.abstractmethod
     4     def read(self):
     5         pass
     6     @abc.abstractmethod
     7     def write(self):
     8         pass
     9 class Txt(File):
    10     def read(self):
    11         pass
    12     def write(self):
    13         pass
    14 p=Txt()

    继承搜索顺序:
    Python2中,分为
    广度优先(新式类)F->D->B->A->E->C->H
    深度优先(经典类)F->D->B->E->C->H->A
    Python3中,只有广度优先(python3中只有新式类)

     1 class A:
     2     def test(self): print('from A')
     3     pass
     4 class B(A):
     5     def test(self): print('from B')
     6     pass
     7 class C(A):
     8     def test(self): print('from C')
     9     pass
    10 class D(B):
    11     def test(self): print('from D')
    12     pass
    13 class E(C):
    14     def test(self): print('from E')
    15     pass
    16 class H(A):
    17     def test(self): print('from H')
    18     pass
    19 class F(D,E,H):
    20     def test(self): print('from F')
    21     pass
    22 f=F()
    23 f.test()
    24 print(F.mro())
    25 #[<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>,
    26 # <class '__main__.C'>, <class '__main__.H'>, <class '__main__.A'>, <class 'object'>]

    子类中重用父类的方法(super)

     1 class Foo:
     2     def test(self):
     3         print('from foo.test')
     4 class Bar(Foo):
     5     def test(self):
     6         super().test()
     7         print('from bar.test')
     8 b = Bar()
     9 b.test()
    10 
    11 class Foo1:
    12     def test(self):
    13         print('from foo1.test')
    14 class Foo2:
    15     def test(self):
    16         print('from foo2.test')
    17 class Bar(Foo1,Foo2):
    18     def test(self):
    19         super().test()
    20         print('from bar.test')
    21 b = Bar()
    22 b.test() #from foo1.test
    23          #from bar.test

    多态与多态性

    没有多态就没有多态性
    多态:同一种事物的多种形态
    多态性:指的是具有不同功能的函数可以使用相同的函数名

     1 class Animal:
     2     def eat(self):
     3         print('eating...')
     4 class People(Animal):
     5     def eat(self):
     6         print('eating...')
     7 class Pig(Animal):
     8     def eat(self):
     9         print('eating...')
    10 class Dog(Animal):
    11     def eat(self):
    12         print('eating...')
    13 p1=People()
    14 g1=Pig()
    15 d1=Dog()
    16 def func(obj):
    17     obj.eat()
    18 func(p1)
    19 func(g1)
    20 func(d1)

    封装

    为什么要封装:保护隐私,隔离复杂度
    Python没有真正的隐藏,只是从语法级别做了些改变

     1 class Foo:
     2     __x = 1 # '_Foo__x': 1
     3     def __test(self): # '_Foo__test': <function Foo.__test at 0x00665D68>
     4         print('from test')
     5 print(Foo.__dict__)
     6 print(Foo._Foo__x)
     7 print(Foo._Foo__test)
     8 
     9 class People:
    10     __country = 'Chinese'
    11     def __init__(self,name,age,sex):
    12         self.__name=name #只在定义阶段才会发生变形,实例产生后新加入的变量就不会变形了
    13         self.__age=age
    14         self.__sex=age
    15     def tell_info(self):
    16         print('%s:%s:%s' % (self.__name,self.__age,self.__sex))
    17 p=People('alex',18,'male')
    18 print(p.__dict__) #{'_People__age': 18, '_People__sex': 18, '_People__name': 'alex'}
    19 p.tell_info()
    20 p.__salary = 3000
    21 print(p.__dict__) #{'_People__name': 'alex', '_People__sex': 18, '_People__age': 18, '__salary': 3000}
    22 
    23 class People:
    24     __country = 'Chinese'
    25     def __init__(self,name,age):
    26         self.__name=name
    27         self.__age=age
    28     def tell_info(self):
    29         print('Name:%s,Age:%d' % (self.__name,self.__age))
    30     def set_info(self,x,y):
    31         if not isinstance(x,str):
    32             raise TypeError('must be str!!!')
    33         if not isinstance(y,int):
    34             raise TypeError('must be int!!!')
    35         self.__name = x
    36         self.__age = y
    37 p1 = People('Albert',18)
    38 p1.tell_info() # Name:Albert,Age:18
    39 p1.set_info('Baker',22)
    40 p1.tell_info() # Name:Baker,Age:22

    关于property的应用

     1 应用1:
     2 class Foo:
     3     @property
     4     def test(self):
     5         print('from foo')
     6     # test = property(test)
     7 f=Foo()
     8 # f.test() #from foo
     9 f.test #from foo
    10 
    11 应用2:
    12 class People:
    13     def __init__(self,name,weight,height):
    14         self.name = name
    15         self.weight = weight
    16         self.height = height
    17     @property
    18     def bmi(self):
    19         return self.weight / (self.height ** 2)
    20 p = People('Albert',75,1.80)
    21 p.height=1.82
    22 print(p.bmi)
    23 
    24 应用3:
    25 import math
    26 class Circle:
    27     def __init__(self,radius):
    28         self.raduis = radius
    29     @property
    30     def zc(self):
    31         return 2 * math.pi * self.raduis
    32 c = Circle(5)
    33 print(c.zc)
    34 
    35 应用4:
    36 class Person:
    37     def __init__(self,name,permission=False):
    38         self.__name = name
    39         self.permission = permission
    40     @property
    41     def name(self):
    42         return self.__name
    43     @name.setter
    44     def name(self,value):
    45         if not isinstance(value,str):
    46             raise TypeError('must be str')
    47         self.__name = value
    48     @name.deleter
    49     def name(self):
    50         if not self.permission:
    51             raise PermissionError('not allowed')
    52         del self.__name
    53 p=Person('Albert')
    54 print(p.name)
    55 p.name='Baker'
    56 print(p.name)
    57 p.permission = True
    58 del p.name

    绑定

    类中定义的函数分成两大类:
    1.绑定方法(绑定给谁,谁来调用就自动将它本身当作第一个参数传入)
      1.绑定到类的方法:用classmethod装饰器装饰的方法。
        为类量身定制
        类.bound_method(),自动将类当作第一个参数传入(其实对象也可调用,但仍将类当作第一个参数传入)
      2.绑定到对象的方法:没有被任何装饰器装饰的方法。
        为对象量身定制
        对象.bound_method(),自动将对象当作第一个参数传入(属于类的函数,类可以调用,但是必须按照函数的规则来,没有自动传值的说法)

    2.非绑定方法:用staticmethod装饰器装饰的方法
      不与类或对象绑定,类和对象都可以调用,但是没有自动传值那么一说,就是一个普通工具而已

     1 #绑定到类的方法
     2 class Foo:
     3     @classmethod
     4     def test(cls):
     5         print(cls)
     6 Foo.test() #<class '__main__.Foo'>
     7 #跟谁都不绑定的方法
     8 class Foo:
     9     @staticmethod
    10     def test(x,y):
    11         print('test',x,y)
    12 Foo.test(1,3)
    13 f=Foo()
    14 f.test(2,4)

    示例

     1 #setting文件配置
     2 # HOST = '127.0.0.1'
     3 # PORT = 3306
     4 import setting
     5 import hashlib
     6 import time
     7 class MySQL:
     8     def __init__(self,host,port):
     9         self.sql_id = self.sql_id()
    10         self.host = host
    11         self.port = port
    12         print('connecting...')
    13     @classmethod
    14     def from_conf(cls):
    15         return cls(setting.HOST,setting.PORT) #相当于MySQL(host,port)
    16     @staticmethod
    17     def sql_id():
    18         m = hashlib.md5(str(time.clock()).encode('utf-8'))
    19         return m.hexdigest()
    20     def select(self):
    21         print(self) #<__main__.MySQL object at 0x0060E2D0>
    22         print('select func',self.host,self.port)
    23 
    24 conn1 = MySQL('192.168.1.1',3306)
    25 conn1.select()
    26 print(conn1.sql_id)
    27 conn2 = MySQL.from_conf()
    28 print(conn2.sql_id)

    staticmeth与classmethod的区别

     1 class Person:
     2     def __init__(self,name,age):
     3         self.name = name
     4         self.age = age
     5     def __str__(self):
     6         print('run __str__')
     7         return 'name:%s age:%s' % (self.name, self.age)
     8 p = Person('Albert',19)
     9 print(p)
    10 
    11 #setting文件配置
    12 # HOST = '127.0.0.1'
    13 # PORT = 3306
    14 import setting
    15 class MySQL:
    16     def __init__(self,host,port):
    17         self.host = host
    18         self.port = port
    19         print('connecting...')
    20     @classmethod
    21     def from_conf(cls):
    22         return cls(setting.HOST, setting.PORT)
    23     def __str__(self):
    24         return 'from MySQL'
    25 class Mariadb(MySQL):
    26     def __str__(self):
    27         print(self.host,self.port)
    28         return 'from Maria'
    29 conn1 = Mariadb.from_conf()
    30 print(conn1)

    反射(自省)

    反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问,检测和修改它本身状态或行为的一种能力。
    Python面向对象中的反射:通过字符串的形式操作对象相关的属性。Python中的一切皆对象(都可以使用反射)

     1 class People:
     2     country = 'China'
     3     def __init__(self,name,age):
     4         self.name=name
     5         self.age=age
     6 print(People.country)
     7 p = People('Albert',18)
     8 print(p)
     9 print(hasattr(p,'name')) # True
    10 print(hasattr(People,'country')) #True
    11 setattr(p,'sex','male')
    12 print(p.__dict__) # {'age': 18, 'name': 'Albert', 'sex': 'male'}
    13 print(getattr(p,'nam','not exist')) # not exist
    14 print(getattr(p,'name'))
    15 # setattr(p,'x',1)
    16 if hasattr(p,'x'):
    17     res = getattr(p,'x')
    18     print(res)
    19 delattr(p,'sex')
    20 print(p.__dict__)

    练习

     1 import sys
     2 res = sys.modules[__name__] #获取当前模块 <module '__main__' from 'C:/Users/ajiax/PycharmProjects/Python17/Day07/ALesson07.py'>
     3 print(res)
     4 if hasattr(res,'People'):
     5     get = getattr(res,'People')
     6     print(get)
     7     obj=get('Baker',22)
     8 print(obj.name)
     9 
    10 
    11 class FTPClient:
    12     def __init__(self,host):
    13         self.host=host
    14         print('connecting...%s' % self.host)
    15     def interactive(self):
    16         while True:
    17             cmd_line = input('>>>:').strip()
    18             cmd_list = cmd_line.split()
    19             if hasattr(self,cmd_list[0]):
    20                 func = getattr(self,cmd_list[0])
    21                 func(cmd_list)
    22     def get(self,args):
    23         print('downloading...%s' % args[1])
    24 p = FTPClient('127.0.0.1')
    25 p.interactive()
  • 相关阅读:
    ural(Timus) 1019 Line Painting
    ACMICPC Live Archive 2031 Dance Dance Revolution
    poj 3321 Apple Tree
    其他OJ 树型DP 选课
    poj 3548 Restoring the digits
    ACMICPC Live Archive 3031 Cable TV Network
    递归循环获取指定节点下面的所有子节点
    手动触发asp.net页面验证控件事件
    子级Repeater获取父级Repeater绑定项的值
    没有列名的数据绑定
  • 原文地址:https://www.cnblogs.com/paodanke/p/6999876.html
Copyright © 2011-2022 走看看