Py学习  »  Python

php python样式的函数变量[重复]

tolgatasci • 5 年前 • 1976 次点击  

PHP 4/5在调用、跳过不想指定的参数时是否可能指定一个命名的可选参数(如在Python中)?

类似于:

function foo($a,$b='', $c='') {
    // whatever
}


foo("hello", $c="bar"); // we want $b as the default, but specify $c

谢谢

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/46202
 
1976 次点击  
文章 [ 17 ]  |  最新文章 5 年前
binki
Reply   •   1 楼
binki    9 年前

只需使用drupal使用的关联数组模式。对于可选的默认参数,只接受 $options 参数,它是关联数组。然后使用数组 + 运算符设置数组中任何缺少的键。

function foo ($a_required_parameter, $options = array()) {
    $options += array(
        'b' => '',
        'c' => '',
    );
    // whatever
}

foo('a', array('c' => 'c’s value')); // No need to pass b when specifying c.
Francisco Luz
Reply   •   2 楼
Francisco Luz    10 年前

这里有一个解决方案:

function set_param_defaults($params) {
  foreach($params['default_values'] as $arg_name => $arg_value) {
    if (!isset($params[$arg_name])) {
      $params[$arg_name] = $arg_value;
    }
  }

  return $params;
}

function foo($z, $x = null, $y = null) {
  $default_values = ['x' => 'default value for x', 'y' => 'default value for y'];
  $params = set_param_defaults(get_defined_vars());

  print "$z\n";
  print $params['x'] . "\n";
  print $params['y'] . "\n";
}

foo('set z value', null, 'set y value');
print "\n";
foo('set z value', 'set x value');

或者: 就我个人而言,我会采用这种方法。

function foo($z, $x_y) {
  $x_y += ['x' => 'default value for x', 'y' => 'default value for y'];

  print "$z\n";
  print $x_y['x'] . "\n";
  print $x_y['y'] . "\n";
}

foo('set z value', ['y' => 'set y value']);
print "\n";
foo('set z value', ['x' => 'set x value']);

两个例子的打印输出。

第一呼叫:

  • 集合Z值
  • X的默认值
  • 集合Y值

第二呼叫:

  • 集合Z值
  • 集X值
  • Y的默认值
Nadir Sampaoli
Reply   •   3 楼
Nadir Sampaoli    13 年前

你不能用python的方式。另外,您可以传递关联数组,然后按其名称使用数组项:

function test ($args=array('a'=>'','b'=>'','c'=>''))
{
    // do something
}

test(array('c'=>'Hello'));

这并不减少打字,但至少它更具描述性,在调用中参数的名称是可见的和可读的。

James Butler
Reply   •   4 楼
James Butler    13 年前

很短,有时是的,通过使用反射和类型变量。但是我想这可能不是你想要的。

解决问题的更好方法可能是在函数自己处理函数中缺少的参数时传递3个参数

<?php  
   function test(array $params)
   {
     //Check for nulls etc etc
     $a = $params['a'];
     $b = $params['b'];
     ...etc etc
   }
Jujhar Singh
Reply   •   5 楼
Jujhar Singh    13 年前

简单的回答。不,你不能。
您可以尝试通过传入对象/数组或使用其他依赖注入模式来绕过它。

此外,尝试使用空值而不是空字符串,因为使用iSnull()测试它们的存在更为明确。

如:

function test ($a=null,$b=null,$c=null){
 if (is_null($a) {
  //do something about $a
 }
 if (is_null($b) {
  //do something about $b
 }
 if (is_null($c) {
  //do something about $c
 }
}

叫这个:

test(null,null,"Hello");
user1299518
Reply   •   6 楼
user1299518    13 年前

我不这么认为… 如果你需要打电话,例如 substr 函数,它有3个参数,并希望 设置 美元的长度 没有 设置$start,你将被迫这样做。

substr($str,0,10);

一个很好的方法就是总是使用 数组 对于参数

RSM
Reply   •   7 楼
RSM    13 年前

尝试 function test ($a="",$b="",&$c=""){}

& 之前 $c

Rene Pot
Reply   •   8 楼
Rene Pot    13 年前

不是真的。你可以使用一些替代品。

test(null,null,"hello")

或传递数组:

test(array('c' => "hello"));

那么,函数可以是:

function test($array) { 
    $c = isset($array[c]) ? $array[c] : '';
}

或者在两者之间添加一个函数,但我不建议这样做:

function ctest($c) { test('','',$c); }
Ville Laurikari
Reply   •   9 楼
Ville Laurikari    14 年前

这是我一直在用的东西。函数定义接受一个可选的数组参数,该参数指定可选的命名参数:

function func($arg, $options = Array()) {
  $defaults = Array('foo' => 1.0,
                    'bar' => FALSE);
  $options = array_merge($default, $options);

  // Normal function body here.  Use $options['foo'] and
  // $options['bar'] to fetch named parameter values.
  ...
}

通常可以在不使用任何命名参数的情况下调用:

func("xyzzy")

要指定可选的命名参数,请将其传入可选数组:

func("xyzzy", Array('foo' => 5.7))
Erick
Reply   •   10 楼
Erick    11 年前

通常不能,但我认为有很多方法可以将命名参数传递给php函数。就我个人而言,我使用数组来传递定义,然后调用需要传递的内容:

class Test{
    public $a  = false;
    private $b = false;
    public $c  = false;
    public $d  = false;
    public $e  = false;
    public function _factory(){
        $args    = func_get_args();
        $args    = $args[0];
        $this->a = array_key_exists("a",$args) ? $args["a"] : 0;
        $this->b = array_key_exists("b",$args) ? $args["b"] : 0;
        $this->c = array_key_exists("c",$args) ? $args["c"] : 0;
        $this->d = array_key_exists("d",$args) ? $args["d"] : 0;
        $this->e = array_key_exists("e",$args) ? $args["e"] : 0;
    }
    public function show(){
        var_dump($this);
    }
}


$test = new Test();
$args["c"]=999;
$test->_factory($args);
$test->show();

这里有一个实例: http://sandbox.onlinephpfunctions.com/code/d7f27c6e504737482d396cbd6cdf1cc118e8c1ff

如果我必须传递10个参数,其中3个是我真正需要的数据,那么传递到函数中是不明智的,比如

return myfunction(false,false,10,false,false,"date",false,false,false,"desc");

使用我给出的方法,可以将10个参数中的任意一个设置为数组:

$arr['count']=10;
$arr['type']="date";
$arr['order']="desc";
return myfunction($arr);

我在我的博客上有一篇文章更详细地解释了这个过程。

http://www.tbogard.com/2013/03/07/passing-named-arguments-to-a-function-in-php

Canuck
Reply   •   11 楼
Canuck    13 年前

您可以通过传递对象而不是数组来保持phpdoc和设置默认值的能力,例如。

class FooOptions {
  $opt1 = 'x';
  $opt2 = 'y';
  /* etc */
};

如果要执行以下操作,还可以在函数调用中执行严格的类型检查:

function foo (FooOptions $opts) {
  ...
}

当然,您可能会为设置foooptions对象而付出额外的代价。不幸的是,这里没有完全免费的交通工具。

David
Reply   •   12 楼
David    15 年前

有些人可能会说,这并不十分漂亮,但它确实很成功。

class NamedArguments {

    static function init($args) {
        $assoc = reset($args);
        if (is_array($assoc)) {
            $diff = array_diff(array_keys($assoc), array_keys($args));
            if (empty($diff)) return $assoc;
            trigger_error('Invalid parameters: '.join(',',$diff), E_USER_ERROR);
        }
        return array();
    }

}

class Test {

    public static function foobar($required, $optional1 = '', $optional2 = '') {
        extract(NamedArguments::init(get_defined_vars()));
        printf("required: %s, optional1: %s, optional2: %s\n", $required, $optional1, $optional2);
    }

}

Test::foobar("required", "optional1", "optional2");
Test::foobar(array(
    'required' => 'required', 
    'optional1' => 'optional1', 
    'optional2' => 'optional2'
    ));
davethegr8
Reply   •   13 楼
davethegr8    15 年前

对于php,参数的顺序才是最重要的。您不能指定不适当的特定参数,但是可以通过传递null来跳过参数,只要您不介意函数中的值具有null值。

foo("hello", NULL, "bar");
Petter Kjelkenes
Reply   •   14 楼
Petter Kjelkenes    10 年前

至于 PHP 5.4 你有速记数组语法(没有必要用繁琐的数组来指定数组),而是使用“[]”。

你可以 模仿 命名参数有很多种方法,一种简单有效的方法可能是:

bar('one', ['a1' => 'two', 'bar' => 'three', 'foo' => 'four']);
// output: twothreefour

function bar ($a1, $kwargs = ['bar' => null, 'foo' => null]) {
    extract($kwargs);
    echo $a1;
    echo $bar;
    echo $foo;
}
Alix Axel
Reply   •   15 楼
Alix Axel    15 年前

不,不是。

唯一可以做的方法是使用带有命名键的数组,而不是什么。

Jon
Reply   •   16 楼
Jon    13 年前

不,php不能按名称传递参数。

如果有一个函数需要很多参数,而所有参数都有默认值,则可以考虑让该函数接受一个参数数组:

function test (array $args) {
    $defaults = array('a' => '', 'b' => '', 'c' => '');
    $args = array_merge($defaults, array_intersect_key($args, $defaults));

    list($a, $b, $c) = array_values($args);
    // an alternative to list(): extract($args);

    // you can now use $a, $b, $c       
}

See it in action .

Pascal MARTIN
Reply   •   17 楼
Pascal MARTIN    15 年前

不,这是不可能的:如果你想通过第三个参数,你必须通过第二个参数。并且命名参数也是不可能的。


一个“解决方案”是只使用一个参数,一个数组,并且总是通过它…但不要总是定义其中的一切。

例如:

function foo($params) {
    var_dump($params);
}

这样称呼:

foo(array(
    'a' => 'hello',
));

foo(array(
    'a' => 'hello',
    'c' => 'glop',
));

foo(array(
    'a' => 'hello',
    'test' => 'another one',
));

将获得以下输出:

array
  'a' => string 'hello' (length=5)

array
  'a' => string 'hello' (length=5)
  'c' => string 'glop' (length=4)

array
  'a' => string 'hello' (length=5)
  'test' => string 'another one' (length=11)

但我不太喜欢这样的解决方案:

  • 你会失去phpdoc的
  • 您的IDE将不能提供任何提示了…哪一个不好

因此,我只在非常具体的情况下才这样做,例如对于具有很多opTyn参数的函数,例如…