函数内函数中的变量/可选参数

时间:2020-11-03 23:15:21

标签: python function arguments sentinel1 sentinelsat

我正在编写一个脚本,让我连接到Sentinel卫星数据库以下载请求的地图文件。

from sentinelsat import SentinelAPI, read_geojson, geojson_to_wkt

def get_available(input_geojson, user, password, date_start, date_end, satellite, sensormode, product_type):

    # LogIn
    api = SentinelAPI(user, password , 'https://scihub.copernicus.eu/dhus')

    # Input parameter of the search
    footprint = geojson_to_wkt(read_geojson(input_geojson))   # irrelevant to the question
    products = api.query(footprint,
                         date = (date_start, date_end),
                         platformname = satellite,
                         sensoroperationalmode = sensormode,
                         producttype = product_type,
                         )

我的问题取决于我将使用哪种“卫星”输入,它将改变哪些其他参数是必需的,必需的甚至允许的。一些不需要“ sensormode”,而另一些则需要“ cloudcoverage”。如何在函数内的函数中编写带有变量/可选参数的干净代码?我必须列出所有可能的论点吗?

3 个答案:

答案 0 :(得分:1)

该API似乎太乏味了,无法使用。最好将参数与类分组。

from sentinelsat import SentinelAPI, read_geojson, geojson_to_wkt


class Satellite:
    def __init__(self, name, producttype, sensormode=None, cloudcoverage=None):
        self.name = name
        self.producttype = producttype
        self.sensormode = sensormode
        self.cloudcoverage = cloudcoverage


class SentinelConnection:
    def __init__(self, input_geojson, user, password):
        self.input_geojson = input_geojson
        self.user = user
        self.password = password
        self.api = None
        self.footprint = None

    def __enter__(self):
        self.api = SentinelAPI(self.user, self.password,
                               'https://scihub.copernicus.eu/dhus')
        self.footprint = geojson_to_wkt(read_geojson(self.input_geojson))

    def __exit__(self, exc_type, exc_val, exc_tb):
        # logout here
        pass


def get_available(conn, satellite, date_start, date_end):
    s = satellite
    products = conn.api.query(conn.footprint,
                              date=(date_start, date_end),
                              platformname=satellite,
                              sensoroperationalmode=s.sensormode,
                              producttype=s.product_type,
                              )


def main():
    with SentinelConnection("abc.json", "name", "password") as conn:
        satellite = Satellite('Sputnik X', 'military satellite')
        get_available(conn, satellite, date_start, date_end)

对于足迹,我一无所知。如果不同的查询可以使用不同的足迹,并且查询经常重复使用相同的足迹,则为足迹创建一个Location类。

答案 1 :(得分:1)

我发现“抓取周期”的答案非常Python化且美观,因此我建议您继续使用。无论如何,我在这方面的工作很有趣,所以这是我对您要寻找的内容的解释:)

@RunWith(PowerMockRunner.class)
@PrepareForTest(ExampleClass.class)
public class ExampleClassTest {

    private final ExampleClass exampleClass = new ExampleClass();

    @Test
    public void exceptionIsNotThrownIfCoolObjHasNoErrors() throws Exception {
        CoolObj coolObjMock = Mockito.mock(CoolObj.class);
        PowerMockito.whenNew(CoolObj.class).withNoArguments().thenReturn(coolObjMock);
        Mockito.when(coolObjMock.hasErrors()).thenReturn(false);

        Assertions.assertThatCode(exampleClass::doSomething)
                .doesNotThrowAnyException();
    }

    @Test
    public void exceptionIsThrownIfCoolObjHasErrors() throws Exception {
        CoolObj coolObjMock = Mockito.mock(CoolObj.class);
        PowerMockito.whenNew(CoolObj.class).withNoArguments().thenReturn(coolObjMock);
        Mockito.when(coolObjMock.hasErrors()).thenReturn(true);

        Assertions.assertThatThrownBy(exampleClass::doSomething)
                .isInstanceOf(RuntimeException.class);
    }
}

演示:http://tpcg.io/AONnvHn9

有一些约束使此实现保持简洁:

  • 所有API签名必须唯一。
  • 所有API签名仅接受 关键字参数。

答案 2 :(得分:0)

我相信这可以通过* kwargs很好地解决。这使您可以将任何键盘参数传递给函数,而无需在函数签名中指定,即:

def foobar(foo, **kwargs):
   bar = kwargs["bar"]
   return foo + bar


barfoo = foobar(foo='something', bar='other_thing')