0905

1. 静态方法

class Animal(object):
    def __init__(self,name):
        self.name = name

    @staticmethod     #静态方法的调用方式
    def eat(self,food):
        print(‘% is eating %s‘ % (self.name,food))
d = Animal(‘zhang‘)
d.eat(‘hanb‘)

#直接按上面写然后执行,会报错:TypeError: eat() missing 1 required positional argument: ‘food‘。说是缺少一个food参数,可是我们不是传了一个food参数hanb嘛,我们稍后再说,看下面代码。

class Animal(object):
    def __init__(self,name):
        self.name = name

    @staticmethod
    def eat(food):
        print(‘%s is eating %s‘ % (‘zhangshanci‘,food))
d = Animal(‘zhang‘)
d.eat(‘hanb‘)

#不给eat方法传self了,直接传一个food,代码运行结果:zhangshanci is eating hanb
#这次就没错了,但是类里面的每个方法不是都要传一个self参数嘛,为什么eat不传也不报错呢,接下来看下面的代码,不给eat传任何参数了,

class Animal(object):
    def __init__(self,name):
        self.name = name

    @staticmethod
    def eat():
        print(‘%s is eating %s‘ % (‘zhangshanci‘,‘hanb‘))
d = Animal(‘zhang‘)
d.eat()

#运行结果是:zhangshanci is eating hanb,也没有报错。

#通过上面的例子,我们总结出来,静态方法其实跟类没有半毛钱关系,它只是通过类的实例来调用而已,类的self、类的属性、类的任何任何都不会传给静态方法使用,所以上面的eat(self,food),需要这样用:eat(‘zhangshanci‘,‘chifan‘),手动传给它两个参数,因为eat里的self参数并不是类的对象,而是一个普普通通需要传入的参数而已。

#那么静态方法如何使用类的属性呢,看如下代码:
class Animal(object):
    def __init__(self,name):
        self.name = name

    @staticmethod
    def eat(self):
        print(‘%s is eating %s‘ % (self.name,‘hanb‘))
d = Animal(‘zhang‘)
d.eat(d)

#把类的对象传入eat方法作为一个参数,然后再调用。这样其实没啥卵用,实际工作中好像也没有用到的地方,不过要知道这个方法,遇到了能看懂。

2.类方法

class Animal(object):
    def __init__(self,name):
        self.name = name
    @classmethod
    def eat(self):
        print(‘%s is eating %s‘ % (self.name,‘hanb‘))
d = Animal(‘zhang‘)
d.eat()

#上面的代码报错如下:
#print(‘%s is eating %s‘ % (self.name,‘hanb‘))
#AttributeError: type object ‘Animal‘ has no attribute ‘name‘。说是Animal这个类没有name属性,但是构造方法里明明有啊,我们接着看下面的代码。

class Animal(object):
    name = ‘zhangshanci‘     #加了一个类变量
    def __init__(self,name):
        self.name = name
    @classmethod
    def eat(self):
        print(‘%s is eating %s‘ % (self.name,‘hanb‘))
d = Animal(‘zhang‘)
d.eat()

#结果如下:
#zhangshanci is eating hanb

#由此可见,类方法只能调用类变量。实际工作中也几乎用不到,知道有这个就行了。

3.属性方法

#我们还是一点点来,通过用多个例子的结果慢慢引入属性方法的特点、使用

class Animal(object):
    def __init__(self,name):
        self.name = name
    @property     #定义属性方法的装饰器
    def eat(self):
        print(‘%s is eating %s‘ % (self.name,‘hanb‘))
d = Animal(‘zhang‘)
d.eat()

#上面的代码报错:d.eat()
#TypeError: ‘NoneType‘ object is not callable。说这个eat()方法不能被调用,这是为啥呢,上面的类里都定义了啊,那我们尝试把括号去掉,如下,

class Animal(object):
    def __init__(self,name):
        self.name = name
    @property
    def eat(self):
        print(‘%s is eating %s‘ % (self.name,‘hanb‘))
d = Animal(‘zhang‘)
d.eat     #调用时去掉了括号

#结果:zhang is eating hanb。可见,属性方法的调用方式是把方法像属性那样调用,属性方法就是把一个方法变成一个属性了,不用加括号直接可调用;
#那能不能给属性方法传参数呢?就上面的代码来看是不可以的,因为嫁入eat(self,food)这样定义,那调用时这样写d.eat(‘chirou‘)和这样写d.eat都会报错缺少一个参数。
#那怎么解决呢?既然属性方法是把方法变成了一个属性,属性可以赋值,所以我们利用给属性赋值的方法来把参数传进去,看下面代码,

class Animal(object):
    def __init__(self,name):
        self.name = name
    @property
    def eat(self):
        print(‘%s is eating %s‘ % (self.name,‘baozi‘))
d = Animal(‘zhang‘)
d.eat
d.eat = ‘junzi‘

#直接给属性方法赋值是会报错的:    d.eat = ‘junzi‘
#AttributeError: can‘t set attribute,提示不能设置这个属性,需要特殊处理才能赋值,接着往下看,

class Animal(object):
    def __init__(self,name):
        self.name = name
    @property    #定义属性方法
    def eat(self):
        print(‘%s is eating %s‘ % (self.name,‘baozi‘))
    @eat.setter    #给属性方法赋值
    def eat(self,food):
        print(‘eat set food:‘,food)
d = Animal(‘zhang‘)
d.eat
d.eat = ‘junzi‘

#结果:
#zhang is eating baozi
#eat set food: junzi
#可见,直接调用属性方法,它会执行@property下面的方法;给属性方法赋值,会执行@eat.setter下面的方法;他俩的方法名必须是一样的,这样就起到了给属性方法传参数的效果。(d.eat = ‘juanzi‘ 就好像是 d.eat(‘jaunzi‘))

下面的代码依然是给属性方法传参,更接近实际使用,如下,
class Animal(object):
    def __init__(self,name):
        self.name = name
        self.__food = None
    @property
    def eat(self):
        print(‘%s is eating %s‘ % (self.name,self.__food))
    @eat.setter
    def eat(self,food):
        self.__food = food
d = Animal(‘zhang‘)
d.eat = ‘junzi‘     #先给属性赋值(也就是变相的传参)
d.eat    #再调用属性

#结果:
#zhang is eating junzi  #本来self.__food是None,经过d.eat=‘juanzi‘后,d.eat再执行时self.__food就变成了juanzi。

接下来的问题是,既然属性方法是一个属性,那怎么删除呢?我们还是直接删除看看,
class Animal(object):
    def __init__(self,name):
        self.name = name
        self.__food = None
    @property
    def eat(self):
        print(‘%s is eating %s‘ % (self.name,self.__food))
    @eat.setter
    def eat(self,food):
        self.__food = food
d = Animal(‘zhang‘)
d.eat
d.eat = ‘junzi‘
d.eat
del d.eat    #尝试删除这个属性
#结果报错:del d.eat
#AttributeError: can‘t delete attribute,提示不能删除这个属性,跟设置属性值一样,我们需要稍微处理一下,代码如下,

class Animal(object):
    def __init__(self,name):
        self.name = name
        self.__food = None
    @property
    def eat(self):
        print(‘%s is eating %s‘ % (self.name,self.__food))
    @eat.setter
    def eat(self,food):
        self.__food = food
    @eat.deleter   #删除属性方法的装饰器
    def eat(self):
        del self.__food
        print(‘delete self.__food‘)
d = Animal(‘zhang‘)
d.eat
d.eat = ‘junzi‘
d.eat
del d.eat     #删除属性d.eat
d.eat

#结果:
#zhang is eating None
#zhang is eating junzi
#delete self.__food
#   print(‘%s is eating %s‘ % (self.name,self.__food))
#AttributeError: ‘Animal‘ object has no attribute ‘_Animal__food‘,提示Animal这个类对象没有__food变量,这是因为执行del d.eat时调用了[email protected]下面的方法,方法里有个del self.__food,既然删了自然就找不到了。

#总结:直接调用属性方法,会调用@property下面的方法;给属性方法赋值,会调用@func_name.setter下面的方法;删除属性方法,会调用@func.deleter下面的方法;至于各个方法里写什么就比较灵活了,写什么执行什么。

好吧,把一个方法变成静态属性有什么卵用呢?既然想要静态变量,那直接定义成一个静态变量不就得了么?well, 以后你会需到很多场景是不能简单通过 定义 静态属性来实现的, 比如 ,你想知道一个航班当前的状态,是到达了、延迟了、取消了、还是已经飞走了, 想知道这种状态你必须经历以下几步:

1. 连接航空公司API查询

2. 对查询结果进行解析

3. 返回结果给你的用户

因此这个status属性的值是一系列动作后才得到的结果,所以你每次调用时,其实它都要经过一系列的动作才返回你结果,但这些动作过程不需要用户关心, 用户只需要调用这个属性就可以,明白 了么?实例代码如下,

class Flight(object):
    def __init__(self,name):
        self.flight_name = name

    def checking_status(self):
        print("checking flight %s status " % self.flight_name)
        return  1

    @property
    def flight_status(self):
        status = self.checking_status()
        if status == 0 :
            print("flight got canceled...")
        elif status == 1 :
            print("flight is arrived...")
        elif status == 2:
            print("flight has departured already...")
        else:
            print("cannot confirm the flight status...,please check later")

    @flight_status.setter #修改
    def flight_status(self,status):
        status_dic = {
            0 : "canceled",
            1 :"arrived",
            2 : "departured"
        }
        print("\033[31;1mHas changed the flight status to \033[0m",status_dic.get(status) )

    @flight_status.deleter  #删除
    def flight_status(self):
        print("status got removed...")

f = Flight("CA980")
f.flight_status
f.flight_status =  2 #触发@flight_status.setter
del f.flight_status #触发@flight_status.deleter 

5.类的特殊成员方法

1. __doc__  打印类的描述信息,类的描述信息一般写在类名的下一行。

class Foo:
    """ 描述类信息,这是用于看片的神奇 """

    def func(self):
        pass

print Foo.__doc__
#输出:类的描述信息

2. __module__ 和  __class__ 

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

__class__     显示当前操作的对象的是哪个类

在lib下建一个aa模块,内容如下:

class C(object):
def __init__(self):
self.name = ‘zsc‘

然后在lib的同级目录建立一个index模块,把aa模块的类C导入到index,如下图,

可见,__module__打印出了这个对象是从哪包导入过来的;__class__打印出了这个对象是哪个类实例出来的。

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

4.__del__

 析构方法,当对象在内存中被释放时,自动触发执行。

#注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的

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

class Dog(object):
    def __init__(self):
        self.name = ‘zsc‘

d = Dog()
d()
直接在对象后面加括号调用,会报错:d()
#TypeError: ‘Dog‘ object is not callable

class Dog(object):
    def __init__(self):
        self.name = ‘zsc‘
    def __call__(self,*args,**kwargs):
        print(‘this is call,‘,args,kwargs)
d = Dog()
d(1,2,3,name=‘zsc‘)

#结果:
#this is call, (1, 2, 3) {‘name‘: ‘zsc‘}
#可见,当在对象后面加括号时会调用这个对象的类的__call__方法。

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

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

class Dog(object):
    def __init__(self):
        self.name = ‘zsc‘
d = Dog()
print(d)
#结果:<__main__.Dog object at 0x0000026023C5C4A8>

class Dog(object):
    def __init__(self):
        self.name = ‘zsc‘
    def __str__(self, *args, **kwargs):  #加了个__str__方法。
        return "<obj:%s>" % self.name
d = Dog()
print(d)
#结果:<obj:zsc>
#可见__str__方法可以控制打印对象时的返回值。

8.__getitem__、__setitem__、__delitem__

使方法变得可以像字典一样使用,下面代码,

class Dog(object):
    def __init__(self):
        self.data = {}
    def __getitem__(self,key):
        print(‘get‘)
        return self.data.get(key)
    def __setitem__(self,key,value):
        self.data[key] = value
        print(‘set‘)
    def __delitem__(self,key):
        del self.data[key]
        print(‘del‘)
d = Dog()
print(d[‘name‘])
print(‘----------------------‘)
d[‘name‘] = ‘zsc‘
print(d[‘name‘])
print(‘----------------------‘)
del d[‘name‘]
print(d[‘name‘])

#结果:
#get
None
----------------------
set
get
zsc
----------------------
del
get
None

可见,取值调用__getitem__方法;设置值调用__setitem__方法;删除值调用__delitem__方法。

9. __new__ \ __metaclass__

9.1 type类
class Foo(object):
    def __init__(self,name):
        self.name = name
obj = Foo("alex")

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

如果按照一切事物都是对象的理论:obj对象是通过执行Foo类的构造方法创建,那么Foo类对象应该也是通过执行某个类的 构造方法 创建。

print type(obj) # 输出:<class ‘__main__.Foo‘>     表示,obj 对象由Foo类创建
print type(Foo) # 输出:<type ‘type‘>              表示,Foo类对象由 type 类创建

所以,obj对象是Foo类的一个实例Foo类对象是 type 类的一个实例,即:Foo类对象 是通过type类的构造方法创建。

其实创建类有两种方式,

a).普通方式:
class Foo(object):
    def func(self):
        print ‘hello zsc‘
b). 特殊方式
def func(self):
    print ‘hello zsc‘

Foo = type(‘Foo‘,(object,), {‘talk‘: func})
#type第一个参数:类名
#type第二个参数:当前类的基类
#type第三个参数:类的成员

用特殊方式创建带有构造函数的类,

def func(self):
    print("hello %s"%self.name)

def __init__(self,name,age):
    self.name = name
    self.age = age
Foo = type(‘Foo‘,(object,),{‘func‘:func,‘__init__‘:__init__})

f = Foo("jack",22)
f.func()

#加上构造方法

所以请记住,类是由type类实例化产生的。

那么问题来了,类默认是由 type 类实例化产生,type类中如何实现的创建类?类又是如何创建对象?

答:类中有一个属性 __metaclass__,其用来表示该类由 谁 来实例化创建,所以,我们可以为 __metaclass__ 设置一个type类的派生类,从而查看 类 创建的过程。

9.2 __new__方法
class Foo(object):
    def __init__(self):
        print(‘__init‘)
    def __new__(cls, *args, **kwargs):
        print(‘__new‘)
        return object.__new__(cls, *args, **kwargs)

obj = Foo()

#结果:
__new
__init
#可见实例化Foo对象后,会调用__init__和__new__方法,而且__new__方法在__init__之前被调用。

下面我们注释了__new__里的return,
class Foo(object):
    def __init__(self):
        print(‘__init‘)
    def __new__(cls, *args, **kwargs):
        print(‘__new‘)
#         return object.__new__(cls, *args, **kwargs)

obj = Foo()

#结果:__new。发现没有调用__init__方法,不是说所有类实例化时都会执行__init__方法吗?原因是,所有类的基类object里有一个__new__方法,这个方法会去调用类里的__init__方法,假如子类重写了__new__方法同时又不调用object.__new__方法的话,就会出现上面的情况;在obj = Foo()等于没有实例化对象。

#注:__new__里的cls参数实际是Foo这个类,把这个类传给了__new__方法。

#作用:假如有一些方法是需要在构造方法之前执行的,就可以重写__new__方法。
9.3 __metaclass__

这个的话,了解了解吧,基本上讲了一个意思:创建对象的的过程是,object类里的__call__方法调用__new__方法,并且生成一个obj的内存地址(其实就是实例出的类对象),然后__new__方法调用__init__方法并且把刚才生成的内存地址传入__init__。这就比较底层了,比如想要所有创建的类都有一个默认的字典,则可以在object的__call__方法里定义一个字典,这样所有的子类都默认都一个字典了。

7.反射

hasattr,判断一个对象里是否有对应的字符串的方法或属性,例如:hasattr(obj,string),有就返回True,没有就返回False。

getattr,getattr(obj,string),如果input_string是一个方法,此处会根据这个字符串获取对象obj里对应的方法的内存地址;如果input_string是一个属性值,此处会根据这个字符串获取对象obj里对应的属性值,而不是内存地址了。

setattr,通过字符串设置新的属性或方法;setattr(obj,string,z) ,把obj这个对象的string(可以是属性或方法)设置为z(可以是一个方法或者一个属性值)。

delattr,delattr(obj,string),删除obj这个对象里的string(可以是方法或者属性)。

下面的代码使用到了hasattr、getattr、setattr、delattr,

def talk(name):
    print(‘this is talk %s‘ % name)

class Foo(object):
    def __init__(self):
        self.name = ‘zsc‘
    def eat(self):
        print(‘%s is eating.‘ % self.name)

obj = Foo()
choice = input(‘>>‘)
if hasattr(obj, choice):     #判断是否有用户输入的方法
    getattr(obj, choice)()   #如果有,就调用这个方法;如果choice是个属性,就去掉后面的括号。
else:
    setattr(obj, choice, talk)   #如果没有就设置这个方法,设置为已有的talk方法
    getattr(obj, choice)(‘zhangshanci‘)
delattr(obj, choice)     #删除这个方法
getattr(obj, choice)()   #删除后,再用getattr就会报错:没有对应方法。

9.异常处理

try:
    code
except error as e:    #捕捉一个异常
    print(e)
except (error1,error2) as e:    #捕捉多个异常
    print(e)
except Exception as e:    #捕捉所有异常,建议放在最后,因为它的范围太大,不好定位异常。
    print(e)
时间: 2024-08-12 08:24:22

0905的相关文章

拆箱装箱 页面跳转 及内存管理 0905蓝懿教育

拆箱装箱 数组中只能装入对象,而很多时候我们需要把类似Int 或者结构体这种装入 此时我们需要进行拆装 基本思想是 把类似int还有结构体 转换成相对应的对象 然后加入数组 ,导出时 要从对象型变成对应的int或者结构体类 @property NSmutableArray *ages; self.ages=[NSmutableArray  Array]; int x=1; NSnumber *objectnumber=x; [self.ages addobject:objectnumber];

汉企0905上午课

网页: 网页基础知识 : 一:HTML语言(超文本标记语言) 二:分类 1.静态页面:页面内容是代码写死的 .HTML .HTL 2.动态页面:页面内容是从数据库读的 .php .asps .jsp 三:工具(DW) 1.代码 2.拆分 3.设计 四:基础语法 1.最小单元称为标签(细胞) 2.双标签元素 ①由两个标签组成 ②<标签名 属性>内容 ③作用:主要作为内容的容器 3.单标签元素 ①<标签名 属性>或<标签名 属性/>都可以 ②由一个标签组成 ③作用:一般起控

汉企0905下午课

通用标签.属性        一.<body>属性:                 1. bgcolor 背景色                 2. text 字体颜色                 3. background背景图片        二.路径                 1. 绝对路径:                  从根开始的路径(C盘里面所有的文件的根都是C)                  /  代表某一个文件夹里面 2.相对路径: 从自身开始的    

__x__(4)0905第二天__网页三大组成部分

根据W3C标准,将网页主要分成3个部分:结构,表现,行为. 结构:HTML用于描述页面结构. 表现:CSS用于控制页面中元素的样式. 行为:JavaScript用于响应用户操作. 原文地址:https://www.cnblogs.com/tianxiaxuange/p/9593920.html

__x__(6)0905第二天__标签属性=“值”

<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>显示在网页的标题栏</title> </head> <body> <h1>Hello,<font color="red" size="7">Web!`</font></h1> <

__x__(7)0905第二天__HTML的发展

HTML的发展 浏览器各个厂商有不同的标准,一个网页的兼容性非常差. 于是,W3C出来了,作为公益组织定义了HTML标准. 在1993.6实现并发布了第一个HTML. 在1995.11开始创主标准,HTML2.0. 在1997.1发布HTML3.2. 在1999.12发布HTML4.01,此时发现HTML语法太松散,直接换到XML. 在2000年底,发布XHTML1.0,因为人们不太接受更严谨的XML. 2004年,W3C全面实行XML标准.此时,苹果.Opera.Mozilla由于更倾向于HT

09-05 绑定方法与非绑定方法

一 绑定方法与非绑定方法 ? 类中定义的函数分为两大类:绑定方法和非绑定方法 ? 其中绑定方法又分为绑定到对象的对象方法和绑定到类的类方法. ? 在类中正常定义的函数默认是绑定到对象的,而为某个函数加上装饰器@classmethod后,该函数就绑定到了类. 插图:恶搞图40 ? 我们在之前的章节中已经介绍过对象方法了,本节我们主要介绍类方法.类方法通常用来在__init__的基础上提供额外的初始化实例的方式 # 配置文件settings.py的内容 HOST='127.0.0.1' PORT=3

Nginx&Apache&PHP参数汇总

1.Nginx vim /etc/nginx/conf.d/www.cmdschool.org.conf   client_max_body_size 30m; //上传文件大小改30M   upstream www.cmdschool.org {     server 10.168.82.25:87;     ip_hash;   }   server {     listen 80;     server_name www.cmdschool.org;     location / {   

js selection省市2级级联菜单

主要分html部分和js部分 ,函数的参数为空时就是初始化状态,若要加载从后台读取数据的数据给option一个选中的初始状态的话,就可以给定参数即可,一下案例中给定了参数. city.html 页面 1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 2 <