Python 函数

Python 函数

Python 函数之定义函数

在Python中,定义一个函数要使用

  • def语句,依次写出函数名、括号、括号中的参数和冒号:
  • 然后,在缩进块中编写函数体,函数的返回值用return语句返回。

1、定义一个函数

def myfirst():
    print("Hello world!")

myfirst()

#输出结果
Hello world!

2、定义发送邮件的函数

  • 不接收用户指定邮箱
# 不接收用户指定邮箱的函数

#!/usr/bin/env python
# -*- conding:utf-8 -*-
import smtplib
from email.mime.text import MIMEText
from email.utils import formataddr

def mail():
    msg = MIMEText('邮件内容', 'plain', 'utf-8')
    msg['From'] = formataddr(["evescn", '18111434862@163.com'])
    msg['To'] = formataddr(["gmkk", '519518995@qq.com'])
    msg['Subject'] = "主题"

    server = smtplib.SMTP("smtp.163.com", 25)
    server.login("18111434862@163.com", "XXXXXX")
    server.sendmail('18111434862@163.com', ['519518995@qq.com', ], msg.as_string())
    server.quit()

mail()
  • 用户可以指定邮箱
# 用户可以指定邮箱的函数

#!/usr/bin/env python
# -*- conding:utf-8 -*-
import smtplib
from email.mime.text import MIMEText
from email.utils import formataddr


def mail(mails):
    msg = MIMEText('邮件内容', 'plain', 'utf-8')
    msg['From'] = formataddr(["evescn", '18111434862@163.com'])
    msg['To'] = formataddr(["gmkk", mails])
    msg['Subject'] = "主题"

    server = smtplib.SMTP("smtp.163.com", 25)
    server.login("18111434862@163.com", "XXXXXX")
    server.sendmail('18111434862@163.com', [mails, ], msg.as_string())
    server.quit()


mail('519518995@qq.com')

3、函数的参数个数

  • 无参
  • 一个参数
  • 两个参数
  • ……
  • 动态参数

4、举例

  • 无参函数
# 无参函数
def show():
    print('a')
    return [11, 22, ]
    print('b')


show()

# 输出结果
a
  • 一个参数
# 一个参数
def show(arg):
    print(arg)

n = [11, 22, 33, 44]
show(n)

# 输出结果
[11, 22, 33, 44]
  • 两个参数
# 两个参数
def show(arg, xxx):
    print(arg, xxx)


show('evescn', 'gmkk')

# 输出结果
evescn gmkk
  • 默认参数
# 默认参数,必须写在实参之后
def jiecheng(arg, n=2):
    print(arg ** n)


jiecheng(2)
jiecheng(2, 3)

# 输出结果
4
8
  • 指定参数
# 指定参数
def show(a1,a2):
    print(a1,a2)


show(123, 999)
show(a2=123, a1=999)

# 输出结果
123 999
999 123
  • 动态参数列表
# 动态参数
# 传入参数为列表  OK?
def show(*arg):   # 把所有位置参数转为了元组
    print(arg, type(arg))

show(1,2,3,4,5,6,7,8)

# 输出结果
(1, 2, 3, 4, 5, 6, 7, 8) <class 'tuple'>
  • 动态参数字典
# 动态参数
# 传入参数为字典  OK?
def show(**arg):  # 把所有关键字参数转为了字典
    print(arg,type(arg))

show(n1=1,n2=2,n3=3,n4=4,)

# 输出结果
{'n4': 4, 'n3': 3, 'n1': 1, 'n2': 2} <class 'dict'>
  • 动态参数
# 实参、一个*的动态参数、两个*的动态参数
# 定义是先放变量,在放一个*的参数,再放**的参数
def show(a1, *args, **kwargs):
    print(a1)
    print(args, type(args))
    print(kwargs, type(kwargs))

show(11, 22, 33, 44, n1=99, n2=88, n3=77)

# 输出结果
11
(22, 33, 44) <class 'tuple'>
{'n3': 77, 'n1': 99, 'n2': 88} <class 'dict'>
  • 动态参数,传入数据类型列表和字典
# 仔细对比2次的输出结果,对于创建的列表和字典,传给函数时需指定传递给那个变量
def show(*args, **kwargs):
    print(args,type(args))
    print(kwargs, type(kwargs))

a1=[11, 22, 33, 44]
a2={'n1': 99, 'n2': 88, 'n3': 77}
show(a1, a2)
show(*a1, **a2)

#输出结果
([11, 22, 33, 44], {'n3': 77, 'n2': 88, 'n1': 99}) <class 'tuple'>
{} <class 'dict'>

(11, 22, 33, 44) <class 'tuple'>
{'n3': 77, 'n2': 88, 'n1': 99} <class 'dict'>
  • format函数
# format函数,如何给farmat函数传递参数
s1 = "{0} to {1}"
l = ['evescn','gmkk']
ret1 = s1.format(*l)
ret2 = s1.format('evescn','gmkk')

print(ret1)
print(ret2)

s1 = "{name} to {acter}"
l = {'name':'evescn', 'acter':'gmkk'}
ret1 = s1.format(**l)
ret2 = s1.format(name='evescn', acter='gmkk')

print(ret1)
print(ret2)

# 输出结果
evescn to gmkk
evescn to gmkk
evescn to gmkk
evescn to gmkk

Python 函数之函数调用

Python内置了很多有用的函数,我们可以直接调用。

要调用一个函数,需要知道函数的名称和参数,比如求绝对值的函数abs,只有一个参数。可以直接从Python的官方网站查看文档:

http://docs.python.org/3/library/functions.html#abs

也可以在交互式命令行通过help(abs)查看abs函数的帮助信息。

1、调用abs函数

>>> abs(100)
100
>>> abs(-20)
20
>>> abs(12.34)
12.34

2、数据类型转换

Python内置的常用函数还包括数据类型转换函数,比如int()函数可以把其他数据类型转换为整数:

>>> int('123')
123
>>> int(12.34)
12
>>> float('12.34')
12.34
>>> str(1.23)
'1.23'
>>> str(100)
'100'
>>> bool(1)
True
>>> bool('')
False

3、函数名

函数名其实就是指向一个函数对象的引用,完全可以把函数名赋给一个变量,相当于给这个函数起了一个“别名”

>>> a = abs # 变量a指向abs函数
>>> a(-1) # 所以也可以通过a调用abs函数
1

4、内置函数

注:查看详细猛击这里

局部变量全局变量

1、全局与局部变量

name = "Evescn"
 
def change_name(name):
    print("before change:",name)
    name = "GMKK"
    print("after change", name)
 
 
change_name(name)
 
print("name: ",name)

# 输出结果
before change: Evescn
after change GMKK
name:  Evescn
  • 在子程序中定义的变量称为局部变量,在程序的一开始定义的变量称为全局变量。
  • 全局变量作用域是整个程序,局部变量作用域是定义该变量的子程序。
  • 当全局变量与局部变量同名时:
  • 在定义局部变量的子程序内,局部变量起作用;在其它地方全局变量起作用。

Python 函数之递归

1、递归函数定义

在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。

我们来计算阶乘 n! = 1 x 2 x 3 x ... x n ,用函数 fact(n) 表示

fact(n) = n! = 1 x 2 x 3 x ... x (n-1) x n = (n-1)! x n = fact(n-1) x n 

所以, fact(n) 可以表示为 n x fact(n-1) ,只有 n=1 时需要特殊处理。

于是, fact(n) 用递归的方式写出来就是

def fact(n):
    if n==1:
        return 1
    return n * fact(n - 1)

上面就是一个递归函数。可以试试:

>>> fact(1)
1
>>> fact(5)
120
>>> fact(100)
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000L  

如果我们计算 fact(5) ,可以根据函数定义看到计算过程如下:

===> fact(5)
===> 5 * fact(4)
===> 5 * (4 * fact(3))
===> 5 * (4 * (3 * fact(2)))
===> 5 * (4 * (3 * (2 * fact(1))))
===> 5 * (4 * (3 * (2 * 1)))
===> 5 * (4 * (3 * 2))
===> 5 * (4 * 6)
===> 5 * 24
===> 120

递归函数的优点是定义简单,逻辑清晰。理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰。

使用递归函数需要注意防止栈溢出。在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。可以试试fact(1000):

>>> fact(1000)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in fact
  ...
  File "<stdin>", line 4, in fact
RuntimeError: maximum recursion depth exceeded in comparison

2、利用函数编写如下数列

斐波那契数列指的是这样一个数列 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,377,610,987,1597,2584,4181,6765,10946,17711,28657,46368 ...

def func(arg1, arg2):
    # for i in range(10):
    if arg1 == 0:
        print(arg1)
        print(arg2)
    arg3 = arg1 + arg2
    if arg3 < 1000:
        print(arg3)
        func(arg2, arg3)
    else:
        return
 
 
func(0, 1)
# 运行结果
0
1
1
2
3
5
8
13
21
34
55
89
144
233
377
610
987

转载自

https://www.liaoxuefeng.com/wiki/1016959663602400/1017268131039072

高阶函数

什么是高阶函数?下面条件满足一个即时高阶函数

  • 把一个函数名当作实参传给另外一个函数(在不修改被装饰函数源代码的情况下为其添加功能)
  • 函数返回值中包含函数名(不修改函数的调用方式)

变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。

def add(x,y,f):
    return f(x) + f(y)
 
 
res = add(3,-6,abs)
print(res) 

函数返回值中包含函数名

def lazy_sum(*args):
    def sum():
        ax = 0
        for n in args:
            ax = ax + n
        return ax
    return sum

当我们调用 lazy_sum() 时,返回的并不是求和结果,而是求和函数:

>>> f = lazy_sum(1, 3, 5, 7, 9)
>>> f
<function lazy_sum.<locals>.sum at 0x101c6ed90>

调用函数 f 时,才真正计算求和的结果:

>>> f()
25

Python 函数之lambda、map、filter和reduce

1、lambda 函数

lambda()是Python里的匿名函数,其语法如下:

lambda [arg1[, arg2, ... argN]]: expression

学习条件运算时,对于简单的 if else 语句,可以使用三元运算来表示,即:

# 普通条件语句
if 1 == 1:
    name = 'evescn'
else:
    name = 'gm'
  
# 三元运算
name = 'evescn' if 1 == 1 else 'gm'

对于简单的函数,也存在一种简便的表示方式,即:lambda表达式

# ###################### 普通函数 ######################
# 定义函数(普通方式)
def func(arg):
    return arg + 1
  
# 执行函数
result = func(123)
  
# ###################### lambda ######################
  
# 定义函数(lambda表达式)
my_lambda = lambda arg : arg + 1
  
# 执行函数
result = my_lambda(123)

lambda存在意义就是对简单函数的简洁表示,下面在举一个列表的例子

l = [11, 22, 33, 44]

new_l = map(lambda x: x + 10, l)

a = list(new_l)
print(a)

# 输出结果
[21, 32, 43, 54]

2、map 函数

map函数会根据提供的函数对指定序列做映射,其语法如下:

map(function, sequence[, sequence, ...]) 

map 函数会对序列参数 sequence 中的每个元素调用 function 函数,返回的结果为每一个元素调用function函数的返回值

l = [11, 22, 33, 44]

def myadd(x):
    return x + 10

new_n = map(myadd, l)

b = list(new_n)
print(b)

# 输出结果
[21, 32, 43, 54]

利用map()函数,把用户输入的不规范的英文名字,变为首字母大写,其他小写的规范名字。输入:['adam', 'LISA', 'barT'],输出:['Adam', 'Lisa', 'Bart']

# -*- coding: utf-8 -*-

def normalize(str):
    return str.capitalize()

# 测试:
L1 = ['adam', 'LISA', 'barT', 'ROOT']
L2 = list(map(normalize, L1))
print(L2)

# 输出结果
['Adam', 'Lisa', 'Bart', 'Root']

3、filter 函数

filter函数会根据提供的函数对指定序列做筛选,其语法如下:

filter(function, iterable) 

filter 函数会对于序列中的元素进行筛选,最终获取符合条件的序列

def myfunc(x):
    if x > 30:
        return True
    else:
        return False

a = [11, 22, 33]

new_a = filter(myfunc,a)

b = list(new_a)
print(b)

# 输出结果
[33]

4、reduce 函数

对于序列内所有元素进行累计操作

reduce 把一个函数作用在一个序列 [x1, x2, x3, ...] 上,这个函数必须接收两个参数, reduce 把结果继续和序列的下一个元素做累积计算,其效果就是:

reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)

比方说对一个序列求和,就可以用 reduce 实现:

>>> from functools import reduce
>>> def add(x, y):
...     return x + y
...
>>> reduce(add, [1, 3, 5, 7, 9])
25

当然求和运算可以直接用Python内建函数 sum() ,没必要动用 reduce

但是如果要把序列 [1, 3, 5, 7, 9] 变换成整数 13579reduce 就可以派上用场:

>>> from functools import reduce
>>> def fn(x, y):
...     return x * 10 + y
...
>>> reduce(fn, [1, 3, 5, 7, 9])
13579

这个例子本身没多大用处,但是,如果考虑到字符串 str 也是一个序列,对上面的例子稍加改动,配合 map() ,我们就可以写出把 str 转换为 int 的函数

>>> from functools import reduce
>>> def fn(x, y):
...     return x * 10 + y
...
>>> def char2num(s):
...     return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s]
...
>>> reduce(fn, map(char2num, '13579'))
13579

整理成一个 str2int 的函数就是:

from functools import reduce

def str2int(s):
    def fn(x, y):
        return x * 10 + y
    def char2num(s):
        return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s]
    return reduce(fn, map(char2num, s))

还可以用 lambda 函数进一步简化成:

from functools import reduce

def char2num(s):
    return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s]

def str2int(s):
    return reduce(lambda x, y: x * 10 + y, map(char2num, s))

也就是说,假设Python没有提供 int() 函数,你完全可以自己写一个把字符串转化为整数的函数,而且只需要几行代码!

转载自

https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/0014317852443934a86aa5bb5ea47fbbd5f35282b331335000

http://www.cnblogs.com/wupeiqi/articles/4943406.html

Python 函数之装饰器

1、函数

#### 第一波 ####
def foo():
    print 'foo'
  
foo     #表示是函数
foo()   #表示执行foo函数
  
#### 第二波 ####
def foo():
    print 'foo'
  
foo = lambda x: x + 1
  
foo()   # 执行下面的lambda表达式,而不再是原来的foo函数,因为函数 foo 被重新定义了

2、需求

初创公司有N个业务部门,1个基础平台部门,基础平台负责提供底层的功能,如:数据库操作、redis调用、监控API等功能。业务部门使用基础功能时,只需调用基础平台提供的功能即可。如下:

############### 基础平台提供的功能如下 ###############
  
def f1():
    print 'f1'
  
def f2():
    print 'f2'
  
def f3():
    print 'f3'
  
def f4():
    print 'f4'
  
############### 业务部门A 调用基础平台提供的功能 ###############
  
f1()
f2()
f3()
f4()
  
############### 业务部门B 调用基础平台提供的功能 ###############
  
f1()
f2()
f3()
f4()

目前公司有条不紊的进行着,但是,以前基础平台的开发人员在写代码时候没有关注验证相关的问题,即:基础平台的提供的功能可以被任何人使用。现在需要对基础平台的所有功能进行重构,为平台提供的所有功能添加验证机制,即:执行功能前,先进行验证。

写代码要遵循开发封闭原则,虽然在这个原则是用的面向对象开发,但是也适用于函数式编程,简单来说,它规定已经实现的功能代码不允许被修改,但可以被扩展,即:

  • 封闭:已实现的功能代码块
  • 开放:对扩展开发

如果将开放封闭原则应用在上述需求中,那么就不允许在函数 f1 、f2、f3、f4的内部进行修改代码

def w1(func):
    def inner():
        # 验证1
        # 验证2
        # 验证3
        return func()
    return inner
  
@w1
def f1():
    print 'f1'
@w1
def f2():
    print 'f2'
@w1
def f3():
    print 'f3'
@w1
def f4():
    print 'f4'

对于上述代码,也是仅仅对基础平台的代码进行修改,就可以实现在其他人调用函数 f1 f2 f3 f4 之前都进行【验证】操作,并且其他业务部门无需做任何操作。

这段代码的内部执行原理是什么呢?

单独以f1为例:

def w1(func):
    def inner():
        # 验证1
        # 验证2
        # 验证3
        return func()
    return inner
  
@w1
def f1():
    print 'f1'

当写完这段代码后(函数未被执行、未被执行、未被执行),python解释器就会从上到下解释代码,步骤如下:

  • def w1(func): ==>将w1函数加载到内存
  • @w1

没错,从表面上看解释器仅仅会解释这两句代码,因为函数在没有被调用之前其内部代码不会被执行。

从表面上看解释器着实会执行这两句,但是 @w1 这一句代码里却有大文章,@函数名 是python的一种语法糖。

如上例@w1内部会执行一下操作:

  • 执行w1函数,并将 @w1 下面的 函数 作为w1函数的参数,即:@w1 等价于 w1(f1)
    所以,内部就会去执行:
    def inner:
        #验证
        return f1()   # func是参数,此时 func 等于 f1
    return inner     # 返回的 inner,inner代表的是函数,非执行函数

其实就是将原来的 f1 函数塞进另外一个函数中

  • 将执行完的 w1 函数返回值赋值给@w1下面的函数的函数名
    w1函数的返回值是:
   def inner:
        #验证
        return 原来f1()  # 此处的 f1 表示原来的f1函数

然后,将此返回值再重新赋值给 f1,即:

    新f1 = def inner:
            #验证
            return 原来f1() 

所以,以后业务部门想要执行 f1 函数时,就会执行 新f1 函数,在 新f1 函数内部先执行验证,再执行原来的f1函数,然后将 原来f1 函数的返回值 返回给了业务调用者。
如此一来, 即执行了验证的功能,又执行了原来f1函数的内容,并将原f1函数返回值 返回给业务调用着

3、装饰器参数

  • 一个参数
### 一个参数
 
def w1(func):
    def inner(arg):
        # 验证1
        # 验证2
        # 验证3
        return func(arg)
    return inner
 
@w1
def f1(arg):
    print 'f1'
  • 两个参数
### 两个参数
def w1(func):
    def inner(arg1,arg2):
        # 验证1
        # 验证2
        # 验证3
        return func(arg1,arg2)
    return inner
 
@w1
def f1(arg1,arg2):
    print 'f1'
  • 三个参数
### 三个参数
 
def w1(func):
    def inner(arg1,arg2,arg3):
        # 验证1
        # 验证2
        # 验证3
        return func(arg1,arg2,arg3)
    return inner
 
@w1
def f1(arg1,arg2,arg3):
    print 'f1'
  • 装饰具有处理n个参数的函数的装饰器
### 装饰具有处理n个参数的函数的装饰器
 
def w1(func):
    def inner(*args,**kwargs):
        # 验证1
        # 验证2
        # 验证3
        return func(*args,**kwargs)
    return inner
  
@w1
def f1(arg1,arg2,arg3):
    print 'f1'
  • 装饰具有处理n个参数的函数的装饰器
### 装饰具有处理n个参数的函数的装饰器
 
def login(func):
    def inner(*args, **kwargs):
        print("passed user bingo")
        return func(*args, **kwargs)
    return inner
 
 
@login
def home():
    print("Welcome to home page!")
 
 
@login
def tv(name):
    print("Welcome %s to tv page!" %name)
    return "gmkk"
 
 
@login
def movie(name, age):
    print("Welcome %s %s to child page" %(name, age))
 
 
home()
t = tv("evescn")
print("T value ", t)
movie("evescn", 15)
 
# 输出结果
passed user bingo
Welcome to home page!
passed user bingo
Welcome evescn to tv page!
T value  gmkk
passed user bingo
Welcome evescn 15 to child page  
  • 一个函数被多个装饰器装饰
### 一个函数被多个装饰器装饰
 
def w1(func):
    def inner(*args,**kwargs):
        # 验证1
        # 验证2
        # 验证3
        return func(*args,**kwargs)
    return inner
  
def w2(func):
    def inner(*args,**kwargs):
        # 验证1
        # 验证2
        # 验证3
        return func(*args,**kwargs)
    return inner
  
  
@w1
@w2
def f1(arg1,arg2,arg3):
    print 'f1'
  • 更吊的装饰器
### 还有什么更吊的装饰器吗?
 
#!/usr/bin/env python
#coding:utf-8
   
def Before(request,kargs):
    print 'before'
       
def After(request,kargs):
    print 'after'
   
   
def Filter(before_func,after_func):
    def outer(main_func):
        def wrapper(request,kargs):
               
            before_result = before_func(request,kargs)
            if(before_result != None):
                return before_result;
               
            main_result = main_func(request,kargs)
            if(main_result != None):
                return main_result;
               
            after_result = after_func(request,kargs)
            if(after_result != None):
                return after_result;
               
        return wrapper
    return outer
       
@Filter(Before, After)
def Index(request,kargs):
    print 'index'
def before1(*request, **kargs):
    print("Before")
 
 
def after1(*request, **kargs):
    print("After")
 
 
# def Filter(before_func, after_func):
#     def login(main_func):
#         def inner(*args, **kwargs):
#             before_func()
#             print("passed user bingo")
#             main_func(*args, **kwargs)
#             after_func()
#             # return func(*args, **kwargs)
#         return inner
#         # return func
#     return login
 
 
def Filter(before_func, after_func):
    def outer(main_func):
        def wrapper(*request, **kargs):
            before_result = before_func(*request, **kargs)
            if (before_result != None):
                return before_result
 
            main_result = main_func(*request, **kargs)
            if (main_result != None):
                return main_result
 
            after_result = after_func(*request, **kargs)
            if (after_result != None):
                return after_result
        return wrapper
    return outer
 
 
@Filter(before1, after1)
def home():
    print("Welcome to home page!")
 
 
@Filter(before1, after1)
def tv(name):
    print("Welcome %s to tv page!" %name)
    return "gmkk"
 
 
def movie(name):
    print("Welcome %s to movie page" %name)
 
 
@Filter(before1, after1)
def child(name, age):
    print("Welcome %s %s to child page" %(name, age))
 
 
home()
t = tv("evescn")
print(t)
child("evescn", 15)
 
# 输出结果
Before
Welcome to home page!
After
Before
Welcome evescn to tv page!
gmkk
Before
Welcome evescn 15 to child page
After

4、functools.wraps

上述的装饰器虽然已经完成了其应有的功能,即:装饰器内的函数代指了原函数,注意其只是代指而非相等,原函数的元信息没有被赋值到装饰器函数内部。例如:函数的注释信息

### 无元信息
 
def outer(func):
    def inner(*args, **kwargs):
        print(inner.__doc__)  # None
        return func()
    return inner
 
@outer
def function():
    """
    asdfasd
    :return:
    """
    print('func')  
 
 
function()
 
# 输出结果
None
func 

如果使用@functools.wraps装饰装饰器内的函数,那么就会代指元信息和函数

### 含元信息

import functools
 
 
def outer(func):
    @functools.wraps(func)
    def inner(*args, **kwargs):
        print(inner.__doc__)  # None
        return func()
    return inner
 
@outer
def function():
    """
    asdfasd
    :return:
    """
    print('func')
 
 
function()
 
# 输出结果
 
    asdfasd
    :return:
     
func 

转载自

http://www.cnblogs.com/wupeiqi/articles/4980620.html
posted @ 2023-06-20 18:28  evescn  阅读(47)  评论(0编辑  收藏  举报