zoukankan      html  css  js  c++  java
  • 面向对象编程进阶

    1、   静态方法staticmethod

    只是名义上归类管理,实际上再静态方法里访问不了类和实例中的任何属性

    定义:

    通过@staticmethod装饰器即可以把其装饰的方法变为一个静态方法,普通的方法可以在实例化之后直接调用,并且在方法里可以通过self调用实例变量或类变量,但静态方法是不可以访问实例变量或类变量。

    如果按照之前学习的面向对象,写一个简单的代码如下:

    1 class Dog(object):    
    2 def __init__(self,name):
    3         self.name = name
    4 
    5     def eat(self,food):
    6         print("%s is eating %s" %(self.name,food))
    7 
    8 d =Dog("小A")
    9 d.eat("包子")

    运行结果如下:

    1 D:python35python.exe D:/python培训/s14/day7/静态方法1.py
    2 小A is eating 包子
    3 
    4 Process finished with exit code 0

    接着对代码进行修改

     1 class Dog(object):
     2 
     3     def __init__(self,name):
     4         self.name = name
     5     @staticmethod  
     6     def eat(self,food):
     7         print("%s is eating %s" %(self.name,food))
     8 
     9 
    10 d = Dog("小A")
    11 d.eat("包子")

    运行结果:

    1 D:python35python.exe D:/python培训/s14/day7/静态方法.py
    2 Traceback (most recent call last):
    3   File "D:/python培训/s14/day7/静态方法.py", line 14, in <module>
    4     d.eat("包子")
    5 TypeError: eat() missing 1 required positional argument: 'food'
    6 
    7 Process finished with exit code 1

    出现了如上述的错误,为了避免food参数的问题,我们再次将代码进行修改:

     1 class Dog(object):
     2 
     3     def __init__(self,name):
     4         self.name = name
     5     @staticmethod
     6     def eat(self):
     7         print("%s is eating %s" %(self.name,"包子"))
     8 
     9 
    10 d = Dog("小A")
    11 d.eat()

    但是运行结果仍然出现如下错误:

    1 D:python35python.exe D:/python培训/s14/day7/静态方法.py
    2 Traceback (most recent call last):
    3   File "D:/python培训/s14/day7/静态方法.py", line 14, in <module>
    4     d.eat()
    5 TypeError: eat() missing 1 required positional argument: 'self'
    6 
    7 Process finished with exit code 1

    其实这就是静态方法,这个时候eat函数和类其实没有上面关系,也可以说静态方法阶段了函数和类的关系

    我们再次将代码进行更改:

     1 class Dog(object):
     2 
     3     def __init__(self,name):
     4         self.name = name
     5     @staticmethod
     6     def eat():
     7         print("%s is eating %s" %("小A","包子"))
     8 
     9 
    10 d = Dog("小A")
    11 d.eat()

    运行结果如下:

    1 D:python35python.exe D:/python培训/s14/day7/静态方法.py
    2 小A is eating 包子
    3 
    4 Process finished with exit code 0

    如果非要传入参数可以将代码更改为,但是下面的代码意义不是特别大:

     1 class Dog(object):
     2 
     3     def __init__(self,name):
     4         self.name = name
     5     @staticmethod
     6     def eat(self):
     7         print("%s is eating %s" %(self.name,"包子"))
     8 
     9 
    10 d = Dog("小A")
    11 d.eat(d)

    运行结果也是正常的

    1 D:python35python.exe D:/python培训/s14/day7/静态方法.py
    2 小A is eating 包子
    3 
    4 Process finished with exit code 0

    2、  类方法classmethod

    类方法只能访问类变量,不能访问实例变量

    我们先写如下代码

    1 #AUTHOR:FAN
    2 class Dog(object):
    3     def __init__(self,name):
    4         self.name = name
    5     @classmethod
    6     def eat(self):
    7         print("%s is eating %s" %(self.name,"包子"))
    8 d = Dog("dean")
    9 d.eat()

    运行结果出现如下错误:

    1 D:python35python.exe D:/python培训/s14/day7/类方法2.py
    2 Traceback (most recent call last):
    3   File "D:/python培训/s14/day7/类方法2.py", line 15, in <module>
    4     d.eat()
    5   File "D:/python培训/s14/day7/类方法2.py", line 7, in eat
    6     print("%s is eating %s" %(self.name,"包子"))
    7 AttributeError: type object 'Dog' has no attribute 'name'
    8 
    9 Process finished with exit code 1

    上述显示无法调用到name

    将代码进行修改

    1 class Dog(object):
    2     name = "AAA"
    3     def __init__(self,name):
    4         self.name = name
    5     @classmethod
    6     def eat(self):
    7         print("%s is eating %s" %(self.name,"包子"))
    8 d = Dog("dean")
    9 d.eat()

    运行效果如下:

    1 D:python35python.exe D:/python培训/s14/day7/类方法2.py
    2 AAA is eating 包子
    3 
    4 Process finished with exit code 0

    从上面的运行结果可以看出虽然我实例化的时候传入了dean但是确实类变量AAA

    3、属性方法property

    将一个方法变成一个静态属性

    我们先写如下代码:

    1 class Dog(object):
    2     def __init__(self,name):
    3         self.name = name
    4     @property
    5     def eat(self):
    6         print("%s is eating %s" %(self.name,"包子"))
    7 d = Dog("dean")
    8 d.eat()

    运行结果如下:

    1 D:python35python.exe D:/python培训/s14/day7/属性方法2.py
    2 dean is eating 包子
    3 Traceback (most recent call last):
    4   File "D:/python培训/s14/day7/属性方法2.py", line 9, in <module>
    5     d.eat()
    6 TypeError: 'NoneType' object is not callable
    7 
    8 Process finished with exit code 1

    所以我将代码进行修改(将d.eat()改为d.eat):

    1 #AUTHOR:FAN
    2 class Dog(object):
    3     def __init__(self,name):
    4         self.name = name
    5     @property
    6     def eat(self):
    7         print("%s is eating %s" %(self.name,"包子"))
    8 d = Dog("dean")
    9 d.eat

    运行结果如下:

    1 D:python35python.exe D:/python培训/s14/day7/属性方法2.py
    2 dean is eating 包子
    3 
    4 Process finished with exit code 0

    从上面可以看出将一个方法变成一个静态属性

    但是这个时候也同样发现无法传参数了。并且及时是已经是一个静态属性了,也是不能赋值的

    如果想要赋值,可以将代码进行如下修改:

     1 class Dog(object):
     2     def __init__(self,name):
     3         self.name = name
     4         self.__food = None
     5     @property
     6     def eat(self):
     7         print("%s is eating %s" %(self.name,self.__food))
     8     @eat.setter
     9     def eat(self,food):
    10         print("set to food:",food)
    11         self.__food = "包子"
    12 d = Dog("dean")
    13 d.eat
    14 d.eat="包子"
      d.eat

    运行结果如下:

    1 D:python35python.exe D:/python培训/s14/day7/属性方法2.py
    2 dean is eating None
    3 set to food: 包子
    4 dean is eating 包子
    5 
    6 Process finished with exit code 0

    这样通过上面的方法就可以对其作为属性进行赋值修改

    但是默认情况下属性方法是无法删除的,如果想要删除,需要:

     1 #AUTHOR:FAN
     2 class Dog(object):
     3     def __init__(self,name):
     4         self.name = name
     5         self.__food = None
     6     @property
     7     def eat(self):
     8         print("%s is eating %s" %(self.name,self.__food))
     9     @eat.setter
    10     def eat(self,food):
    11         print("set to food:",food)
    12         self.__food = "包子"
    13     @eat.deleter
    14     def eat(self):
    15         del self.__food
    16         print("删完了")
    17 
    18 d = Dog("dean")
    19 d.eat
    20 d.eat="包子"
    21 d.eat
    22 del d.eat

    运行结果如下:

    1 D:python35python.exe D:/python培训/s14/day7/属性方法2.py
    2 dean is eating None
    3 set to food: 包子
    4 dean is eating 包子
    5 删完了
    6 
    7 Process finished with exit code 0

    4、 类的特殊成员方法

    __doc__表示类的描述信息

    __module__表示当前操作的对象在哪个模块

    __class__表示当前操作的对象的类是什么

    __init__构造方法,通过类创建对象时,自动触发执行

    __del__ 析构函数,当对象在内存中释放时,自动触发执行

    __call__对象后面加括号,触发执行

    代码例子:

     1 class Dog(object):
     2 
     3     def __init__(self,name):
     4         self.name = name
     5     # @staticmethod
     6     def eat(self,food):
     7         print("%s is eating %s" %(self.name,food))
     8     def __call__(self, *args, **kwargs):
     9         print("running call",args,kwargs)
    10 
    11 
    12 d = Dog("小A")
    13 d(1,2,3,4,name="dean")

    运行结果如下:

    1 D:python35python.exe D:/python培训/s14/day7/静态方法.py
    2 running call (1, 2, 3, 4) {'name': 'dean'}
    3 
    4 Process finished with exit code 0

    __dict__查看类或对象中的所有成员

    代码例子:

     1 class Dog(object):
     2 
     3     def __init__(self,name):
     4         self.name = name
     5     # @staticmethod
     6     def eat(self,food):
     7         print("%s is eating %s" %(self.name,food))
     8     def __call__(self, *args, **kwargs):
     9         print("running call",args,kwargs)
    10 
    11 
    12 d = Dog("小A")
    13 # d(1,2,3,4,name="dean")
    14 print(Dog.__dict__)
    15 print(d.__dict__)

    运行结果如下:

    1 D:python35python.exe D:/python培训/s14/day7/静态方法.py
    2 {'__doc__': None, 'eat': <function Dog.eat at 0x0000000000B6E378>, '__init__': <function Dog.__init__ at 0x0000000000B6E2F0>, '__weakref__': <attribute '__weakref__' of 'Dog' objects>, '__call__': <function Dog.__call__ at 0x0000000000B6E400>, '__dict__': <attribute '__dict__' of 'Dog' objects>, '__module__': '__main__'}
    3 {'name': '小A'}
    4 Process finished with exit code 0

    从上面例子也可以看出print(Dog.__dict__)打印类里的所有属性,不包括实例属性

    print(d.__dict__)打印所有实例属性,不包括类属性

    __str__如果一个类中定义了__str__方法,那么在打印对象时,默认输出该方法的返回值

    __getitem__ __setitem__ __telitem__

    用于索引操作,如字典。以上分别表示获取,设置、删除数据

    __new__

    代码如下:

    1 class Foo(object):
    2     def __init__(self,name):
    3         self.name = name
    4 
    5 f = Foo("dean")
    6 print(type(f))
    7 
    8 print((type(Foo)))

    在上述代码中f是通过Foo实例化的对象,其实不仅f是一个对象,Foo类本身也是一个对象,因为在python中一切事物都是对象

    运行结果如下:

    1 D:python35python.exe D:/python培训/s14/day7/__new__.py
    2 <class '__main__.Foo'>
    3 <class 'type'>
    4 
    5 Process finished with exit code 0

    上面的输出同样表示了:

    <class ‘__main__.Foo’>表示f对象由Foo类创建

    <class 'type'> 表示Foo类对象由type类创建

     

    所以从上面也可以得出f对象时Foo类的一个实例,Foo类对象时type类的一个实例,即Foo类对象时通过type类构造方法创建的

    所以创建类就可以有两种方法:

    普通方法

    1 class Foo(object):
    2     def func(self):
    3         print("hello dean")

    特殊方法

    1 def func(self):
    2     print("hello dean")
    3 Foo = type('Foo',(object,),{'talk':func})
    4 f = Foo()
    5 f.talk()
    6 print(type(Foo))

    运行结果如下:

    1 D:python35python.exe D:/python培训/s14/day7/__new__.py
    2 hello dean
    3 <class 'type'>
    4 
    5 Process finished with exit code 0

    从这里也可以看出type就是类的类,所有的类都是通过type创建的

    将上述代码进行修改:

     1 def func(self):
     2     print("hello dean")
     3     
     4 def __init(self ,name,age):
     5     self.name = name
     6     self.age = age
     7 Foo = type('Foo',(object,),{'talk':func,
     8                             '__init__':__init})
     9 f = Foo("dean",23)
    10 print(f.name)
    11 print(f.age)
    12 f.talk()
    13 print(type(Foo))

    运行结果如下:

    1 D:python35python.exe D:/python培训/s14/day7/__new__.py
    2 dean
    3 23
    4 hello dean
    5 <class 'type'>
    6 
    7 Process finished with exit code 0

    5、 反射

    getattr(obj,name_str)判断一个对象obj里是否有对应name_str的字符串的方法映射

    getattr(obj,name_str) 根据字符串去获取obj对象里的对应的方法的内存地址

    代码例子:

     1 class Dog(object):
     2     def __init__(self,name):
     3         self.name = name
     4     
     5     def eat(self):
     6         print("%s is eating..." %self.name)
     7 
     8 
     9 d = Dog("dean")
    10 choice = input(">>>:").strip()
    11 #
    12 # print(hasattr(d,choice))
    13 # print(getattr(d,choice))
    14 #
    15 # getattr(d,choice)()
    16 if hasattr(d,choice):
    17     func = getattr(d,choice)
    18     func()

    运行结果如下:

    1 D:python35python.exe D:/python培训/s14/day7/反射1.py
    2 >>>:eat
    3 dean is eating...
    4 
    5 Process finished with exit code 0

    如果输入的字符串对应的方法不存在的情况让添加外面的类:代码如下,

     1 def bulk(self):
     2         print("%s is yelling....." %self.name)
     3 
     4 class Dog(object):
     5     def __init__(self,name):
     6         self.name = name
     7 
     8     def eat(self):
     9         print("%s is eating..." %self.name)
    10 
    11 
    12 d = Dog("dean")
    13 choice = input(">>>:").strip()
    14 
    15 if hasattr(d,choice):
    16         func = getattr(d,choice)
    17 func()
    18 else:
    19         setattr(d,choice,bulk)
    20         d.talk(d)

    运行结果如下:

    1 D:python35python.exe D:/python培训/s14/day7/反射1.py
    2 >>>:talk
    3 dean is yelling.....
    4 
    5 Process finished with exit code 0

    setattr(obj,’y’,z) 相当于x.y = v

    代码例子:

    1 if hasattr(d,choice):
    2     func = getattr(d,choice)
    3     func()
    4 else:
    5     setattr(d,choice,22)
    6     print(getattr(d,choice))

    删除是delattr(d,choice)

    6、异常处理

    语法:

    1 try:
    2         pass
    3 except Exception as e:
    4         pass

    一个简单的例子:

    1 name =[1,2,3]
    2 
    3 try:
    4         name[4]
    5 except IndexError as e:
    6         print(e)

    如果想要同时抓多个错误的方法:

    1 try:
    2         code
    3 except(Error1,Error2) as e:
    4         print(e)

    如果想要一次性抓住所有错误可以用Exceptions(一般不用,无法定位错误,但是一般放到最后面,用于提示未知错误):

    1 name =[1,2,3]
    2 
    3 try:
    4         name[4]
    5 except Exceptions e:
    6         print(e)

    else 表示一切正常

    finally 表示不管有没有错都执行

    一些常见的异常:

     1 AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x
     2 IOError 输入/输出异常;基本上是无法打开文件
     3 ImportError 无法引入模块或包;基本上是路径问题或名称错误
     4 IndentationError 语法错误(的子类) ;代码没有正确对齐
     5 IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]
     6 KeyError 试图访问字典里不存在的键
     7 KeyboardInterrupt Ctrl+C被按下
     8 NameError 使用一个还未被赋予对象的变量
     9 SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了)
    10 TypeError 传入对象类型与要求的不符合
    11 UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,
    12 导致你以为正在访问它
    13 ValueError 传入一个调用者不期望的值,即使值的类型是正确的

    自定义异常代码例子:

     1 class myerror(Exception):
     2         def __init__(self, msg):
     3             self.message = msg
     4 
     5 try:
     6         name = []
     7         name = [3]
     8         raise myerror('我的异常')
     9 except myerror as e:
    10         print(e)

    运行结果如下:

    1 D:python35python.exe D:/python培训/s14/day7/自定义异常.py
    2 我的异常
    3 
    4 Process finished with exit code 0

    7、 socket编程

    一个简单的例子:

    服务端:

     1 import socket
     2 server = socket.socket()
     3 server.bind(('127.0.0.1',6969)) #绑定要监听的端口
     4 server.listen()#监听
     5 
     6 print("我要开始等电话了")
     7 #conn就是客户端连过来而在服务器端为其生成的一个连接实例
     8 conn,addr = server.accept()#等待电话打来
     9 
    10 print("电话来了")
    11 
    12 data = conn.recv(1024)
    13 print("recv:",data)
    14 conn.send(data.upper())
    15 
    16 server.close()

    客户端:

     1 import socket
     2 
     3 client = socket.socket()
     4 client.connect(('127.0.0.1',6969))
     5 
     6 client.send(b"Hello world")
     7 data = client.recv(1204)
     8 print("recv:",data)
     9 
    10 client.close()

    先运行服务端,在运行客户端,结果如下:

     1 D:python35python.exe D:/python培训/s14/day7/socket_server1.py
     2 我要开始等电话了
     3 电话来了
     4 recv: b'Hello world'
     5 
     6 Process finished with exit code 0
     7 D:python35python.exe D:/python培训/s14/day7/socket_client1.py
     8 recv: b'HELLO WORLD'
     9 
    10 Process finished with exit code 0

    将上述代码进行改进:

    服务端:

     1 import socket
     2 server = socket.socket()
     3 server.bind(('127.0.0.1',6969)) #绑定要监听的端口
     4 server.listen()#监听
     5 
     6 print("我要开始等电话了")
     7 while True:
     8     # conn就是客户端连过来而在服务器端为其生成的一个连接实例
     9     conn, addr = server.accept()  # 等待电话打来
    10     print("电话来了")
    11     while True:
    12         data = conn.recv(1024)
    13         print("recv:",data)
    14         if not data:
    15             print("client has lost....")
    16             break
    17         conn.send(data.upper())
    18 server.close()

    客户端:

     1 import socket
     2 
     3 client = socket.socket()
     4 client.connect(('127.0.0.1',6969))
     5 while True:
     6         msg = input(">>:").strip()
     7         client.send(msg.encode("utf-8"))
     8         data = client.recv(1204)
     9         print("recv:",data.decode())
    10 
    11 client.close()

    上述代码改进后可以在客户端断开后,服务端不会进入死循环没如果这个时候有新的客户端进入,可以继续通讯

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

  • 相关阅读:
    iOS 苹果开发证书失效的解决方案(Failed to locate or generate matching signing assets)
    iOS NSArray数组过滤
    App Store2016年最新审核规则
    iOS 根据字符串数目,自定义Label等控件的高度
    iOS 证书Bug The identity used to sign the executable is no longer valid 解决方案
    Entity FrameWork 增删查改的本质
    EF容器---代理类对象
    Entity FrameWork 延迟加载本质(二)
    Entity FrameWork 延迟加载的本质(一)
    Entity FrameWork 增删查改
  • 原文地址:https://www.cnblogs.com/zhaof/p/5849764.html
Copyright © 2011-2022 走看看